(本文为Android官方开发文档译文)
转载自:http://blog.csdn.net/yichigo/article/details/8472570
使用Wi-Fi Direct技术可以让具备硬件支持的设备在没有中间接入点的情况下进行直接互联。Android 4.0(API版本14)及以后的系统都提供了对Wi-Fi Direct的API支持。通过对这些API的使用,开发者可以实现支持Wi-Fi Direct的设备间进行相互探测和连接,从而获得较之蓝牙更远距离的高速数据通信效果。对于诸如多人游戏、图片共享等需要在用户之间传输数据的应用而言,这一技术无疑是十分有价值的。
关于Wi-Fi Direct的API函数的使用需要注意一下几个要点:
·用于探测(discover)对等设备(peers)、向对等设备发起请求(request)以及建立连接(connect)的方法定义在类WifiP2pManager中。
·通过设置监听器(Listener)可以获知WifiP2pManager中方法调用的成功与否。监听器以参数的形式传递给被调用的方法。
·当发现新对等设备或链接丢失的时候,Wi-Fi Direct系统(framework)以意向(Intent)的方式根据检测到的不同事件做出相应的通知。
开发中,以上三点的配合使用相当普遍。简单举个例子,定义一个监听器WifiP2pManager.ActionListener并调用函数discoverPeers(),当相应事件发生的时候就会在ActionListener.onSuccess()和ActionListener.onFailure()两个方法中得到通知。当discoverPeers()方法检测到了对等设备列表变化的时候,可以收到由系统广播(broadcast)发出一个WIFI_P2P_PEERS_CHANGED_ACTION意向。
API概述(API Overview)
WifiP2pManager类所提供的方法可用于操作当前设备中的Wi-Fi硬件,实现诸如探测对、连接对等设备等功能。目前所支持的功能如下:
表 1.Wi-Fi Direct Methods
Method |
Description |
initialize() |
Registers the application with the Wi-Fi framework. This must be called before calling any other Wi-Fi Direct method. |
connect() |
Starts a peer-to-peer connection with a device with the specified configuration. |
cancelConnect() |
Cancels any ongoing peer-to-peer group negotiation. |
requestConnectInfo() |
Requests a device's connection information. |
createGroup() |
Creates a peer-to-peer group with the current device as the group owner. |
removeGroup() |
Removes the current peer-to-peer group. |
requestGroupInfo() |
Requests peer-to-peer group information. |
discoverPeers() |
Initiates peer discovery |
requestPeers() |
Requests the current list of discovered peers. |
WifiP2pManager中所提供的方法允许特定的监听器作为参数传入,以便Wi-Fi Direct机制能够汇报函数调用的结果。下表中列出了目前支持的监听器接口以及WifiP2pManager中用到相应监听器的方法。
表 2. Wi-Fi Direct Listeners
Listener interface |
Associated actions |
WifiP2pManager.ActionListener |
connect(),cancelConnect(),createGroup(),removeGroup(), anddiscoverPeers() |
WifiP2pManager.ChannelListener |
initialize() |
WifiP2pManager.ConnectionInfoListener |
requestConnectInfo() |
WifiP2pManager.GroupInfoListener |
requestGroupInfo() |
WifiP2pManager.PeerListListener |
requestPeers() |
每当有Wi-Fi Direct事件发生的时候(例如,发现新的对等设备、设备的Wi-Fi状态改变等),Wi-Fi Direct API会以广播的形式发出一个意向。而在应用程序中需要做的事情就是创建广播接收器(creating a broadcast receiver)来处理这些意向:
表 3. Wi-Fi Direct Intents
Intent |
Description |
WIFI_P2P_CONNECTION_CHANGED_ACTION |
Broadcast when the state of the device's Wi-Fi connection changes. |
WIFI_P2P_PEERS_CHANGED_ACTION |
Broadcast when you calldiscoverPeers(). You usually want to call requestPeers() to get an updated list of peers if you handle this intent in your application. |
WIFI_P2P_STATE_CHANGED_ACTION |
Broadcast when Wi-Fi Direct is enabled or disabled on the device. |
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION |
Broadcast when a device's details have changed, such as the device's name. |
创建广播接收器以处理Wi-Fi Direct意向(Creating a Broadcast Receiver for Wi-Fi Direct Intents)
广播接收器可以让应用程序接收到Android系统所发出的广播意向。这样,应用程序就能对感兴趣的事件做出响应。创建广播接收器的基本步骤如下:
下面的代码将展示了如何创建一个特定的广播接收器。例子中的广播接收器以WifiP2pManager对象和一个活动(activity)作为参数,并使用它们针对收到的意向(intent)做出相应的动作(action):
创建Wi-Fi Direct应用(Creating a Wi-Fi Direct Application)
完整的Wi-Fi Direct应用包含创建并注册广播接收器、检测对等设备、连接对等设备以及在对等设备间传输数据几个方面的功能。下面将详细介绍如何实现。
准备工作(Initial setup)
在使用Wi-Fi Direct API之前,首先要确保应用程序能够访问硬件,并且设备支持Wi-Fi Direct协议。如果这些条件都满足,就可以获取一个WifiP2pManager实例,创建并注册广播接收器,最后就是使用Wi-Fi Direct API了。
检查Wi-Fi Direct支持并已开启。推荐在广播接收器收到WIFI_P2P_STATE_CHANGED_ACTION意向的时候进行检测。检测结果需要通告相应的活动并做出处理:
在活动的onCreate()方法中获取WifiP2pManager对象的一个实例,通过该对象的initialize()方法向Wi-Fi Direct系统注册当前的应用程序。注册成功后,会返回一个WifiP2pManager.Channel,通过它,应用程序就能和Wi-Fi Direct系统交互。WifiP2pManager和WifiP2pManager.Channel对象以及一个活动的引用最后都被作为参数传递给自定义的广播接收器。这样,该活动就能够响应广播接收器的通知并作出相应的更新。当然,这样做也使程序具备了操纵设备Wi-Fi状态的能力:
创建一个意向过滤器(intent filter),其中添加的意向种类和广播接收器中的保持一致:
在活动的onResume()方法中注册广播接收器,并在活动的onPause()方法中注销它:
一旦成功获取WifiP2pManager.Channel并创建了广播接收器,应用程序就已经具备了使用Wi-Fi Direct相关函数和接收Wi-Fi Direct意向的能力。尽管放手使用WifiP2pManager为你提供的方法,让程序也拥有Wi-Fi Direct的特殊能力吧!
下一节将讲述如何实现一些常见的动作,例如探测并连接到对等设备。
探测对等设备(Discovering peers)
调用discoverPeers()函数可以探测到有效距离内的对等设备。它是一个异步函数,调用成功与否会在程序所创建WifiP2pManager.ActionListener监听器的onSuccess()和onFailure()中给出通知。值得注意的是,onSuccess()方法只会对成功探测到对等设备这一事件做出通知,而并不会提供任何关于已发现的对等设备的具体信息:
当成功检测到对等设备存在的时候,系统会广播WIFI_P2P_PEERS_CHANGED_ACTION意向。程序接收到该意向后,通过调用requestPeers()方法,就能获得已经探测到对等设备的清单。下面代码将展示如何实现这一过程:
requestPeers()方法同样是一个异步函数,当它准备好一份对等设备列表的时候,就会通知监听器WifiP2pManager.PeerListListener中定义的onPeersAvailable()方法。而onPeersAvailable()方法中所能获取到的对等设备列表以WifiP2pDeviceList形式存储,通过遍历这个列表可以选择出希望连接的设备。
连接对等设备(Connecting to peers)
确定了要连接的设备,还需调用connect()方法建立连接。该方法的其中一个参数是WifiP2pConfig对象,它提供了要连接设备的相关信息。连接的成功与否需要通过监听器WifiP2pManager.ActionListener获取通知。下面的代码将示范如何建立设备连接:
传输数据(Transferring data)
连接一旦建立成功,数据传输也就是顺理成章的事情。以下是通过socket发送数据的基本步骤:
以下代码修改自SDK自带的示例Wi-Fi Direct Demo。它演示了如何建立一对客户端-服务器连接,并由客户端向服务器发送JPEG图片。若需完整的演示工程,只需编译并运行SDK示例Wi-Fi Direct Demo即可。
On the client, connect to the server socket with a client socket and transfer data. This example transfers a JPEG file on the client device's file system.
示例代码下载:
http://download.csdn.net/detail/yichigo/5516627
以上示例代码来源于android sdk中自带的例子程序
疑难问题:
Android 4.1之前Wi-Fi P2P极其不稳定。
从Android4.1开始Wi-Fi P2P开始好用一些,但因为和普通Wi-Fi Station模式是可以并存的,会有一定的影响,比如:
1
A手机的Station连接某热点用了某Channel 1,然后A手机与B手机进行P2P协商出的结果是Channel 2。
此时如果Channel 1 不等于Channel 2,那么就不能连接B手机了。
因为每个Channel对应的是一个固定的细分频段,一个手机的Wi-Fi某一时刻只能在一个频段上。
这个问题在Android4.2上会提示频率冲突,可以暂时断开Station与热点的连接,等P2P结束后再恢复。
2
因为系统优先保证Station模式与热点的连接,所以P2P的扫描间隔周期要给热点的扫描周期让步,扫描间隔会比较长。一方面P2P本身还有一些不问题,另一方面,扫描不够及时,所以会发现状态不能及时更新,也不能及时重新扫描、连接。
所以最好升级到4.2影响1可以降低,影响2可以在rom里优化扫描的周期,在应用里优化估计比较困难。
3
通过wifidirect自动协商确定双方谁是客户端谁是服务端,导致A发给B发送完成后A再发送给C,或B再发送给A,此时A被自动分配为服务端,一直监听着端口,提示端口占用,发送失败