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

本阶段的第一节课 Using Network Service Discovery 展示了如何搜索本地网络服务。然而,使用WI-FI P2P搜索服务可以直接搜索附近的设备,而不需要专门通过本地网络。这项特性使得在没有本地网络或者热点的情况下还可以在不同的设备间进行通信。

虽然这里的API与NSD的API的目的很相似,但是实现的过程却完全不同。这节课展示了如何通过WI-FI P2P网络来搜索附近的可用服务。这节课建立在已经对Wi-Fi P2P API熟悉的基础之上。

设置清单文件

如果要使用WI-FI P2P技术,需要在程序的清单文件中添加CHANGE_WIFI_STATE, ACCESS_WIFI_STATE, INTERNET三项权限。虽然Wi-Fi P2P并不需要互联网连接,但是它需要使用标准的Java Socket通讯技术,所以需要使用INTERNET权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.android.nsdchat"...<uses-permissionandroid:required="true"android:name="android.permission.ACCESS_WIFI_STATE"/><uses-permission
        android:required="true"android:name="android.permission.CHANGE_WIFI_STATE"/><uses-permission
        android:required="true"android:name="android.permission.INTERNET"/>...

添加本地服务

如果程序提供了本地服务,还需要将该服务注册到搜索服务中。一旦本地服务完成注册,那么框架会自动的响应另一端点的搜索服务请求。

创建本地网络有以下过程:

  • 1.创建一个WifiP2pServiceInfo对象。
  • 2.将服务的相关信息填入其中。
  • 3.调用addLocalService()方法完成本地服务注册。
     private void startRegistration() {//  Create a string map containing information about your service.Map record = new HashMap();record.put("listenport", String.valueOf(SERVER_PORT));record.put("buddyname", "John Doe" + (int) (Math.random() * 1000));record.put("available", "visible");// Service information.  Pass it an instance name, service type// _protocol._transportlayer , and the map containing// information other devices will want once they connect to this one.WifiP2pDnsSdServiceInfo serviceInfo =WifiP2pDnsSdServiceInfo.newInstance("_test", "_presence._tcp", record);// Add the local service, sending the service info, network channel,// and listener that will be used to indicate success or failure of// the request.mManager.addLocalService(channel, serviceInfo, new ActionListener() {@Overridepublic void onSuccess() {// Command successful! Code isn't necessarily needed here,// Unless you want to update the UI or add logging statements.}@Overridepublic void onFailure(int arg0) {// Command failed.  Check for P2P_UNSUPPORTED, ERROR, or BUSY}});}

搜索附近的服务

Android会使用回调方法来通知应用程序有可用的服务,所以首先要做的就是设置该回调。创建一个WifiP2pManager.DnsSdTxtRecordListener来监听传入的记录。这个记录由其它设备随意广播。当其中一条记录到达时,会将该设备的地址及其它相关的信息拷贝到一个外部的数据结构中,这样的话就可以晚一些访问。下面的代码假设这个记录包含一条”buddyname”的属性,用于识别用户的身份。

final HashMap<String, String> buddies = new HashMap<String, String>();
...
private void discoverService() {DnsSdTxtRecordListener txtListener = new DnsSdTxtRecordListener() {@Override/* Callback includes:* fullDomain: full domain name: e.g "printer._ipp._tcp.local."* record: TXT record dta as a map of key/value pairs.* device: The device running the advertised service.*/public void onDnsSdTxtRecordAvailable(String fullDomain, Map record, WifiP2pDevice device) {Log.d(TAG, "DnsSdTxtRecord available -" + record.toString());buddies.put(device.deviceAddress, record.get("buddyname"));}};...
}

如要获取服务的相关信息,需要创建一个WifiP2pManager.DnsSdServiceResponseListener接口。 这个接口会接收实际的连接信息。上面代码段中的Map对象将设备的地址与”buddy name”组成了键值对。服务响应监听器利用这项特性与DNS记录建立连接。一旦两个监听器都已经实现,那么将它们添加到WifiP2pManager的setDnsSdResponseListeners()方法中即可。

private void discoverService() {
...DnsSdServiceResponseListener servListener = new DnsSdServiceResponseListener() {@Overridepublic void onDnsSdServiceAvailable(String instanceName, String registrationType,WifiP2pDevice resourceType) {// Update the device name with the human-friendly version from// the DnsTxtRecord, assuming one arrived.resourceType.deviceName = buddies.containsKey(resourceType.deviceAddress) ? buddies.get(resourceType.deviceAddress) : resourceType.deviceName;// Add to the custom adapter defined specifically for showing// wifi devices.WiFiDirectServicesList fragment = (WiFiDirectServicesList) getFragmentManager().findFragmentById(R.id.frag_peerlist);WiFiDevicesAdapter adapter = ((WiFiDevicesAdapter) fragment.getListAdapter());adapter.add(resourceType);adapter.notifyDataSetChanged();Log.d(TAG, "onBonjourServiceAvailable " + instanceName);}};mManager.setDnsSdResponseListeners(channel, servListener, txtListener);...
}

接下来需要创建一个新的服务请求,然后将其作为参数调用addServiceRequest()方法,这个方法同样需要一个监听器来反应成功还是失败。

        serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();mManager.addServiceRequest(channel,serviceRequest,new ActionListener() {@Overridepublic void onSuccess() {// Success!}@Overridepublic void onFailure(int code) {// Command failed.  Check for P2P_UNSUPPORTED, ERROR, or BUSY}});

最后,调用discoverServices()方法开始搜索服务。

        mManager.discoverServices(channel, new ActionListener() {@Overridepublic void onSuccess() {// Success!}@Overridepublic void onFailure(int code) {// Command failed.  Check for P2P_UNSUPPORTED, ERROR, or BUSYif (code == WifiP2pManager.P2P_UNSUPPORTED) {Log.d(TAG, "P2P isn't supported on this device.");else if(...)...}});

如果上面的都已经完成,那么可以喊一声哈利路亚了,已经完成了所有的步骤。如果遇到了问题,寻找那个将WifiP2pManager.ActionListener作为参数的方法,这个回调方法会告知程序是成功还是失败。如果要解决这个问题,请将调试代码放入onFailure()方法中。方法所提供的错误代码会告知问题所在。下面是可能出现的错误代码以及它们的解释:

P2P_UNSUPPORTED

    当前设备不支持Wi-Fi P2P

BUSY

    系统处于繁忙处理状态

ERROR

    由于内部错误造成操作失败

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

  1. Android官方开发文档Training系列课程中文版:管理设备的睡眠状态

    原文地址:http://android.xsoftlab.net/training/scheduling/index.html 引言 当Android设备处于闲置状态时,它的屏幕首先会变暗,接着会关闭 ...

  2. Android官方开发文档Training系列课程中文版:目录

    原文地址 : http://android.xsoftlab.net/training/index.html 引言 在翻译了一篇安卓的官方文档之后,我觉得应该做一件事情,就是把安卓的整篇训练课程全部翻 ...

  3. Android官方开发文档Training系列课程中文版:创建自定义View之View的创建

    原文地址:http://android.xsoftlab.net/training/custom-views/index.html 引言 Android框架含有大量的View类,这些类用来显示各式各样 ...

  4. Android官方开发文档Training系列课程中文版:OpenGL绘图之图形绘制

    原文地址:http://android.xsoftlab.net/training/graphics/opengl/draw.html 如果你还不清楚如何定义图形及坐标系统,请移步:Android官方 ...

  5. Android官方开发文档Training系列课程中文版:使用Fragment构建动态UI之Fragment创建

    原文地址:http://android.xsoftlab.net/training/basics/fragments/index.html 导言 为了在Android中创建动态的多面板用户界面,你需要 ...

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

    原文地址:http://android.xsoftlab.net/training/connect-devices-wirelessly/index.html 引言 Android设备除了可以与服务器 ...

  7. Android官方开发文档Training系列课程中文版:调用相机之控制相机

    原文地址:http://android.xsoftlab.net/training/camera/cameradirect.html 在这节课,我们会讨论如何使用Android框架API来直接控制相机 ...

  8. Android官方开发文档Training系列课程中文版:Android的安全建议

    原文地址:http://android.xsoftlab.net/training/articles/security-tips.html Android系统内置的安全策略可以有效的降低应用程序的安全 ...

  9. Android官方开发文档Training系列课程中文版:电池续航时间优化之检查、检测网络连接状态

    原文地址:http://android.xsoftlab.net/training/monitoring-device-state/connectivity-monitoring.html 通常会有一 ...

  10. Android官方开发文档Training系列课程中文版:网络操作之网络管理

    原文地址:http://android.xsoftlab.net/training/basics/network-ops/managing.html 这节课将会学习如何对网络资源的使用情况拥有更细粒度 ...

最新文章

  1. 微信小程序setData()方法的使用
  2. Python学习 day01打卡
  3. python加上子类的特性_Python--面向对象三大特性
  4. Struts2 源码分析——拦截器的机制
  5. EOS 智能合约源代码解读 (5)class contract
  6. 接口幂等性的设计之————redis分布式锁的应用
  7. 怎样实现WPF Prism Module的国际化和本地化?
  8. ArrayList理解(5)与vector区别
  9. 与敏捷团队一起交付价值
  10. Spring框架教程集合
  11. 2021年北京学校高考成绩查询,2021年北京高考成绩查询时间及入口【官方】
  12. AS3学习笔记(一)基础知识
  13. 如何使用go读写excel
  14. oracle alter database close,alter database close
  15. android 修改系统字体后app崩溃,android 应用在切换系统字体大小和语言时,应用崩溃问题...
  16. ERP项目学习(一)
  17. linux 下面dev文件,Linux下目录的含义,例如lib中放置了什么文件,dev是什么
  18. 背景图片渲染时有色块怎么办
  19. C语言例题:温度转换
  20. python机器人库(robotics-toolbox-python)的运用

热门文章

  1. 简单的C语言程序合集
  2. C语言,画吃豆人剖析
  3. python复制sheet_python excel sheet复制
  4. Flink-Sink_将结果输出到Kafka_Redis_ES_Mysql中
  5. linux查看登录服务器的ip历史记录,通过登陆IP记录Linux所有用户登录所操作日志的方法...
  6. docker 虚拟机搭建mongodb一主一从一复制_云计算学习路线图素材课件:Docker容器应用场景分析...
  7. LeetCode 1601. 最多可达成的换楼请求数目(回溯+剪枝)
  8. LeetCode 978. 最长湍流子数组(DP)
  9. LeetCode 934. 最短的桥(2次BFS)
  10. 字符变量赋值规则_Java的常量、变量、数据类型(基础篇二)