Android官方开发文档Training系列课程中文版:连接无线设备之网络服务搜索功能

原文地址:http://android.xsoftlab.net/training/connect-devices-wirelessly/index.html

引言

Android设备除了可以与服务器建立连接之外,Android无线API还允许处于同一网段下的两台设备建立连接,或者是物理距离相近的两台设备建立连接。Network Service Discovery (NSD)允许应用程序通过扫描来搜索附近可连接的设备。当然被扫描的设备也同样需要开启该服务。利用这项特性可以使应用程序拥有更强大的功能,比如和同伴在一个房间内玩游戏,或者从有NSD服务的网络摄像头上下载照片,或者远程操控屋内的其它设备(智能家电的基础)。

这节课将学习如何搜索其它设备并与之建立连接。需要特别说明的是,这些关键的API描述了如何使用NSD API来搜索可用的服务及如何利用Wi-Fi Peer-to-Peer (P2P) API来建立P2P方式的无线连接。这节课还会学习如何使用NSD与WIFI P2P结合的方式来搜索服务提供者。

使用网络搜索服务

使用Network Service Discovery (NSD)服务可以使应用程序搜索处于同一本地网络下的其它支持服务要求的设备。这对多样的P2P应用程序极为有用,比如可以利用这项技术共享文件,或者玩多人游戏。Android的NSD API可以使应用程序快速实现这种功能。

这节课会学习如何构建一个应用程序,这个应用程序需要可以广播程序的名称及连接到本地网络的连接信息及扫描上述信息的功能。最后,这节课会学习如何去其它设备建立连接。

将服务注册到网络

Note: 这节课是可选的,如果不需要将应用的服务广播到本地网络,则可以直接跳到下一段。

为了将服务注册到本地网络上,首先需要创建一个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);....
}

上面的代码将服务的名称设置为”NsdChat”。这个名称对所有使用了USD服务的设备可见。要记住一点就是这个名称在这个网络环境中必须是唯一的,Android会自动处理这种名称冲突问题。如果在同一环境下有两个名称为”NsdChat”的设备,那么Android会自动将其中一个命名为”NsdChat (1)”.

第二个参数设置了该服务的类型,指定了所使用的传输协议与运输层。这个定义语法是”.”.在上面的代码中,该服务使用的是运行在TCP上的HTTP协议。如果一个程序提供的是打印服务,那么它的服务类型应该是”_ipp._tcp”.

Note: 这些搜索服务协议比如NSD、Bonjour由International Assigned Numbers Authority (IANA)互联网地址编码分配机构统一管理。你可以通过the IANA list of service names and port numbers下载服务类型列表。如果计算使用一种新的服务类型,应当在IANA Ports and Service registration form上进行备案。

当为服务设置端口时,应避免将端口写死,因为这个端口可能会与其他端口冲突。假设,应用程序一直在使用端口1337,则会与其它也使用了相同端口的应用程序造成端口冲突,使用设备的下一个可用端口则可以避免这种冲突。因为这个信息是由其它应用通过广播提供的,所以在编译时不需要知道其它应用使用的是哪个接口。相反的,应用程序会在连接到设备之前通过广播获得端口的信息。

如果使用Socket进行通信,下面的代码展示了如何初始化一个Socket,并将其端口设置为万能的端口0.

public void initializeServerSocket() {// Initialize a server socket on the next available port.mServerSocket = new ServerSocket(0);// Store the chosen port.mLocalPort =  mServerSocket.getLocalPort();...
}

那么现在已经定义了NsdServiceInfo对象,接下来还需实现RegistrationListener接口。这个接口用于通知应用程序服务的注册于解注是成功还是失败。

public void initializeRegistrationListener() {mRegistrationListener = new NsdManager.RegistrationListener() {@Overridepublic 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();}@Overridepublic void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {// Registration failed!  Put debugging code here to determine why.}@Overridepublic void onServiceUnregistered(NsdServiceInfo arg0) {// Service has been unregistered.  This only happens when you call// NsdManager.unregisterService() and pass in this listener.}@Overridepublic 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);
}

搜索网络上的服务

网络的世界充满了各种生命,从狂野的网络打印机到温柔的网络摄像头,再到激烈运动的体感游戏机,无不是一种生命。可以使应用程序能够看到这些各式各样的生命体的核心是服务搜索功能。应用程序只需要监听网络上的服务广播就可以判断哪些服务是可用的,哪些是不需要的。

服务搜索功能与服务的注册很类似,也有两个步骤:设置相应的搜索监听器,调用discoverServices()方法。

首先,实例化一个实现了NsdManager.DiscoveryListener接口的匿名类:

public void initializeDiscoveryListener() {// Instantiate a new DiscoveryListenermDiscoveryListener = new NsdManager.DiscoveryListener() {//  Called as soon as service discovery begins.@Overridepublic void onDiscoveryStarted(String regType) {Log.d(TAG, "Service discovery started");}@Overridepublic 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);}}@Overridepublic void onServiceLost(NsdServiceInfo service) {// When the network service is no longer available.// Internal bookkeeping code goes here.Log.e(TAG, "service lost" + service);}@Overridepublic void onDiscoveryStopped(String serviceType) {Log.i(TAG, "Discovery stopped: " + serviceType);}@Overridepublic void onStartDiscoveryFailed(String serviceType, int errorCode) {Log.e(TAG, "Discovery failed: Error code:" + errorCode);mNsdManager.stopServiceDiscovery(this);}@Overridepublic void onStopDiscoveryFailed(String serviceType, int errorCode) {Log.e(TAG, "Discovery failed: Error code:" + errorCode);mNsdManager.stopServiceDiscovery(this);}};
}

NSD API会在这些情况下回调这些方法:搜索服务启动时,搜索服务失败时,服务未找到时,服务丢失时。注意在服务找到时会有以下若干项检查:

  • 1.会对找到的服务名称与本身服务的名称相比较,来判断是否是自己发出的广播。
  • 2.服务类型检查,验证找到的服务是否可以连接。
  • 3.服务名称检查,验证是否连接到了正确的程序上。

服务名称的检查并不是必须的,只有在连接到指定的程序上才会这一步。比如,应用程序只是希望连接其它设备上的相同应用程序。无论如何,如果程序希望连接到网络打印机上时,只需要判断其服务类型是否是”_ipp._tcp”就足够了。

在设置完监听器之后,调用discoverServices(),然后传入程序要监听的服务类型,要使用的搜索协议,及刚刚创建的监听器。

    mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);

连接到网络服务

当应用程序找到网络上的服务并试图与之建立连接时,必须先通过resolveService()方法检查该服务的连接信息。实现NsdManager.ResolveListener接口,然后将其传入方法resolveService()中,然后通过这个接口的回调方法获得一个NsdServiceInfo对象,这个对象包含了所需要的连接信息:

public void initializeResolveListener() {mResolveListener = new NsdManager.ResolveListener() {@Overridepublic void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {// Called when the resolve fails.  Use the error code to debug.Log.e(TAG, "Resolve failed" + errorCode);}@Overridepublic 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();}};
}

一旦解析完成,那么程序就会获得包括IP地址与端口号在内的详细服务信息。这为连接到该服务的网络提供了帮助。

注销服务

在程序的生命周期内可以适当关闭NSD功能是很重要的。在程序关闭时注销服务有助于防止其它程序认为该程序还处于存活状态,并试图与其建立连接。另外,服务搜索功能的代价很高,所以在Activity停止时应当关闭服务,在Activity重新启动时再次打开。应用程序应当重写对应的Activity的生命周期回调方法,并在这些方法中插入适当的代码来启动或者关闭服务广播与服务搜索功能。

//In your application's Activity@Overrideprotected void onPause() {if (mNsdHelper != null) {mNsdHelper.tearDown();}super.onPause();}@Overrideprotected void onResume() {super.onResume();if (mNsdHelper != null) {mNsdHelper.registerService(mConnection.getLocalPort());mNsdHelper.discoverServices();}}@Overrideprotected void onDestroy() {mNsdHelper.tearDown();mConnection.tearDown();super.onDestroy();}// NsdHelper's tearDown methodpublic void tearDown() {mNsdManager.unregisterService(mRegistrationListener);mNsdManager.stopServiceDiscovery(mDiscoveryListener);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/479055.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新年立个小目标!代码写得更规范!

知乎作者叶小飞:作为Oppo Reno2 超级夜景核心开发人员和奔驰San Jos Pilot落地工程师之一,我写代码基本尽可能地遵循Google Style. 在这里写几个自己的习惯Google Style里面几个常用的要点。自己的习惯动手写代码前尽量做到胸中有丘壑。现在这世界讲究格局&#xff…

手把手教你用Keras实现英文到中文机器翻译 seq2seq+LSTM

原文链接:https://blog.csdn.net/qq_44635691/article/details/106919244 该模型实现的是英文到中文的翻译,下图为了更好展示模型架构借用大佬的图(这里没有用到Embeddings): 本文完整代码:Github 目录 一、处理文本数据 1.获得翻译前后的句子…

LeetCode 45. 跳跃游戏 II(贪心/BFS,难)

文章目录1. 题目2. 解题2.1 贪心2.2 BFS1. 题目 给定一个非负整数数组,你最初位于数组的第一个位置。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 你的目标是使用最少的跳跃次数到达数组的最后一个位置。 示例:输入: [2,3,1,1,4] 输出: 2 解释: 跳到最…

Android官方开发文档Training系列课程中文版:连接无线设备之通过WIFI创建P2P连接

原文地址:http://android.xsoftlab.net/training/connect-devices-wirelessly/wifi-direct.html#permissions Wi-Fi peer-to-peer (P2P) APIs可以使程序与附近的设备进行直接通讯,Android的Wi-Fi P2P框架由Wi-Fi Direct™提供技术支持。WI-FI P2P技术可…

深度剖析开源分布式监控CAT

CAT(Central Application Tracking)是一个实时和接近全量的监控系统,它侧重于对Java应用的监控,基本接入了美团上海侧所有核心应用。目前在中间件(MVC、RPC、数据库、缓存等)框架中得到广泛应用&#xff0c…

论文浅尝 | ​ADRL:一个基于注意力机制的知识图谱深度强化学习框架

论文笔记整理:谭亦鸣,东南大学博士。来源:Knowledge-Based Systems 197 (2020) 105910链接:https://www.sciencedirect.com/science/article/abs/pii/S0957417419306839概要与动机知识图谱推理是图谱构建的关键技术之一&#xff0…

新年第二弹|卖萌屋私藏书单大公开

夕本尊 &夕小瑶 推荐作为一个互联网人,不仅要懂技术,还应该了解行业的基本运作原理。这其中一个重要的问题是:为什么互联网产品(基本)都是免费的,甚至纷纷给用户送钱,它们却能有这么强的盈利…

LeetCode 437. 路径总和 III(双重递归)

1. 题目 给定一个二叉树,它的每个结点都存放着一个整数值。 找出路径和等于给定数值的路径总数。 路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。 二叉树不超过…

2020年美团技术团队最受欢迎的16篇技术文章

2020年美团技术团队最受欢迎的16篇技术文章:https://tech.meituan.com/2021/01/01/2020-summary.html

论文浅尝 - ESWA | 知识图谱的自动扩充方法

论文笔记整理:谭亦鸣,东南大学博士。来源:ESWA141(2020)链接:https://www.sciencedirect.com/science/article/abs/pii/S0957417419306839为了使计算机理解人类语言,并且实现推理,人类知识需要被表示并储存…

美团大脑:知识图谱的建模方法及其应用

作为人工智能时代最重要的知识表示方式之一,知识图谱能够打破不同场景下的数据隔离,为搜索、推荐、问答、解释与决策等应用提供基础支撑。美团大脑围绕吃喝玩乐等多种场景,构建了生活娱乐领域超大规模的知识图谱,为用户和商家建立…

Android官方开发文档Training系列课程中文版:连接无线设备之通过P2P搜索网络服务

原文地址:http://android.xsoftlab.net/training/connect-devices-wirelessly/nsd-wifi-direct.html 本阶段的第一节课 Using Network Service Discovery 展示了如何搜索本地网络服务。然而,使用WI-FI P2P搜索服务可以直接搜索附近的设备,而…

全栈深度学习第2期: 开发套件与工具篇

一起追剧鸭简介Berkeley全栈深度学习追剧计划是由夕小瑶的卖萌屋发起的优质公开课打卡项目,通过微信群为同期追剧的小伙伴提供交流平台。关于该计划的详请见这里。1. Berkeley深度学习追剧群目前已有1000小伙伴加入,公众号后台回复口令 深度学习追剧 入群…

LeetCode 700. 二叉搜索树中的搜索

1. 题目 给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。 2. 解题 class Solution {//递归写法TreeNode *ans NULL; public:TreeNode* searchB…

NLP-美团技术团队(搜索-推荐-召回排序-Bert)

NLP-美团技术团队:https://tech.meituan.com/tags/nlp.html

iOS系统中导航栏的转场解决方案与最佳实践

背景 目前,开源社区和业界内已经存在一些 iOS 导航栏转场的解决方案,但对于历史包袱沉重的美团 App 而言,这些解决方案并不完美。有的方案不能满足复杂的页面跳转场景,有的方案迁移成本较大,为此我们提出了一套解决方案…

论文浅尝 - WSDM20 | 基于弱监督及逐步推理的多关系知识图谱问答

论文笔记整理:刘晓臻,东南大学计算机科学与工程学院本科生。来源:WSDM ’20链接:https://dl.acm.org/doi/abs/10.1145/3336191.3371812动机知识图谱问答(KG-QA)系统大多包含两个步骤:链接问题中的topic entity到KG&…

Android官方开发文档Training系列课程中文版:网络操作之网络连接

原文地址:http://android.xsoftlab.net/training/basics/network-ops/index.html 引言 这节课将会学习最基本的网络连接,监视网络连接状况及网络控制等内容。除此之外还会附带描述如何解析、使用XML数据。 这节课所包含的示例代码演示了最基本的网络操…

算法工程师的落地能力具体指的是什么?

文 | 桔了个仔知乎本文已获作者授权,禁止二次转载大家好,这里是桔了个仔,目前是一名Data Scientist(不太想翻译成数据科学家,毕竟感觉自己就是个工程师),过去几年在做基于机器学习的风控与合规系统&#xf…

国内外自然语言处理(NLP)研究组

2015年国内外自然语言处理(NLP)研究组: https://blog.csdn.net/wangxinginnlp/article/details/44890553 补充: 名称 地址 最近更新 HanLP https://github.com/hankcs/HanLP 2天前 腾讯开源深度学习文本分类工具 https://github.com/Tencent/NeuralNLP-…