注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好。

原文链接:http://developer.android.com/training/connect-devices-wirelessly/nsd-wifi-direct.html


在这系列课程的第一节课中(博客链接:http://www.cnblogs.com/jdneo/p/3579936.html),向你展示了如何发现连接到本地网络上的服务。然而,使用Wi-Fi Peer-to-Peer(P2P)服务搜索会允许你直接发现附近设备的服务,而不需要连接到网络中。你也可以对外广播目前正在你的设备上运行的服务。这些功能帮助你和其它应用进行通信,甚至是当无法获取本地网络或者热点的情况下。

虽然此API所要达到的目的,和之前课程中所说的NSD API非常类似,但是实现它们的代码却是不同的。这节课将向你展示如何使用Wi-Fi P2P从其他设备发现可获得的服务。这节课假设你已经对Wi-Fi P2P的API有了一定的了解。


一). 配置清单文件

为了使用Wi-Fi P2P,需要在你的清单文件中添加CHANGE_WIFI_STATEACCESS_WIFI_STATEINTERNET权限。虽然Wi-Fi P2P不需要网络连接,但是它使用的是标准的Java套接字,而在Android中使用它们则需要声明对应的权限许可:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.nsdchat"
... <uses-permission
android: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"/>
...

二). 添加一个本地服务

如果你正在提供一个本地服务,你需要为服务搜索注册它。一旦你的本地服务注册了,框架将会自动响应Peer所发起的服务搜索请求。

要创建一个本地服务:

  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() {
@Override
public void onSuccess() {
// Command successful! Code isn't necessarily needed here,
// Unless you want to update the UI or add logging statements.
} @Override
public 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记录和对应的服务信息连接到一起。一旦这两个监听器都实现了,使用setDnsSdResponseListeners()方法将它们添加到WifiP2pManager中。

private void discoverService() {
... DnsSdServiceResponseListener servListener = new DnsSdServiceResponseListener() {
@Override
public 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() {
@Override
public void onSuccess() {
// Success!
} @Override
public void onFailure(int code) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
}
});

最后,调用discoverServices()

        mManager.discoverServices(channel, new ActionListener() {

            @Override
public void onSuccess() {
// Success!
} @Override
public void onFailure(int code) {
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
if (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 Developers Training】 77. 使用Wi-Fi P2P进行服务搜索的更多相关文章

  1. 【Android Developers Training】 76. 用Wi-Fi创建P2P连接

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  2. 【Android Developers Training】 74. 序言:通过无线连接设备

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  3. 【Android Developers Training】 75. 使用NSD

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  4. 【Android Developers Training】 9. 覆盖于布局之上的Action Bar

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  5. 【Android Developers Training】 8. 定义Action Bar风格

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  6. 【Android Developers Training】 7. 添加Action Buttons

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  7. 【Android Developers Training】 6. 配置Action Bar

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  8. 【Android Developers Training】 5. 序言:添加Action Bar

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  9. 【Android Developers Training】 4. 启动另一个Activity

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

随机推荐

  1. Visual Studio 2017 针对移动开发的新特性介绍

    欢迎大家持续关注葡萄城控件技术团队博客,更多更好的原创文章尽在这里~~ Visual Studio是世界上最好的IDE之一,如果是 .NET世界,那就没有之一了(^_^),而最近推出的Visual S ...

  2. Java过滤敏感词语/词汇---DFA算法

    最近网站需要在评论.投稿等地方过滤敏感词汇,于是在网上查找了相关教程,特此整理分享. 关于DFA算法,详细的可以去http://blog.csdn.net/u013378306/article/det ...

  3. windows 上优雅的安装 node 和 npm

    windows 的一键安装包,应该是最简单的 node 安装方式. 其实很多软件,拷贝过来就可以运行,根本不需要所谓的"安装"过程. 新建一个目录专门了管理 node 和 npm  ...

  4. deepin/ubuntu下搭建Jekyll环境

    title: deepin/ubuntu下搭建Jekyll环境 最近用github搭建了个博客,正好也学习一下markdown语法,由于markdown写完后不是立即可见,所以每次写完文章都要经过在线 ...

  5. 4、Swing在JPanel中添加背景图片方法

    4.Jpanel面板中加载背景图片 在实际应用Java做界面的过程中,常常会涉及到加载背景图片以使页面美化.下面整理了一个小模块以便于调用. 1 package com.tntxia.commonsw ...

  6. 开涛spring3(7.3) - 对JDBC的支持 之 7.3 关系数据库操作对象化

    7.3.1  概述 所谓关系数据库对象化其实就是用面向对象方式表示关系数据库操作,从而可以复用. Spring JDBC框架将数据库操作封装为一个RdbmsOperation,该对象是线程安全的.可复 ...

  7. mysql变量使用总结(转)

    set语句的学习: 使用select定义用户变量的实践将如下语句改成select的形式: set @VAR=(select sum(amount) from penalties);我的修改: sele ...

  8. [原创]CentOS下Mysql的日志回滚

    一.    环境: a)        Centos-6.5-x64位操作系统. b)        安装mysql.命令:yum install mysql* 二.    配置 a)        ...

  9. 《算法4》2.1 - 插入排序算法(Insertion Sort), Python实现

    排序算法列表电梯: 选择排序算法:详见 Selection Sort 插入排序算法(Insertion Sort):非常适用于小数组和部分排序好的数组,是应用比较多的算法.详见本文 插入排序算法的语言 ...

  10. VR全景智慧城市——商家的需求才是全景市场的核心竞争力

    消费者视角痛点:比如酒店消费行业,很多消费者在预订酒店过程中,都遇到过这样的场景:网上照片里酒店房间看着宽敞明亮,格调不凡,感觉非常喜欢,等真正推开房门插上房卡一看,却大失所望.在酒店行业,网上照片和 ...