wifi直连(Android)Wifi-Direct

wifi直连也叫做wifi设备点对点连接(peer-peer),不需要连接热点或者网络,需要打开wifi,就可以查找到附近的设备。大概可以分为以下步骤:1.设置以下权限,并且注意最小sdk=14


2.创建一个广播接收器,通过创建IntentFilter来addAction得到各个特定事件的发生来进行回调.


创建一个新的 BroadcastReceiver 类,用来监听系统的Wi-Fi P2P状态的改变(在 onReceive方法中,添加一个条件来处理上面列出的各种P2P状态的变更。)

 

最后,在主活动**时,注册意图过滤器(Intent Filter)和广播接收器;在主活动暂停时把它们注销。最好在onResume()和onPause()方法中完成该操作。


3.初始化得到WifiP2pManager和Channel实例,在onCreate()方法中初始化,如果是在Fragment中,initialize参数用Looper.getMainLooper(),

4.初始化搜索,只初始化了对等点的搜索。discoverPeers()方法启动了搜索线程,并立刻返回。系统通过调用给定的动作监听器的方法来进行初始化,并会在成功初始化对等点进程时通知你。同时,搜索也会持续进行,直到一个连接被初始化,或者一个P2P组形成。


5.获取搜索到设备列表, 获取对等点的列表并进行处理,首先实现 WifiP2pManager.PeerListListener 接口,它提供了Wi-Fi Direct检测到的对等点信息。注:在公司当时我是在这个方法里实现自动连接,保存到sharedPreference,然后如果有搜索到相同的设备名和地址,代码就不写出来了,有更好的想法的可以说下。

 

在广播onReceive()方法中以便在收到一个带有 WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION 动作的意图(Intent)时调用requestPeers方法。把实现PeerListListener的类作为方法参数传进去进行监听器回调。


6.连接(后面具体说)这个是重点哦

为了连接一个对等点,需要先创建一个新的 WifiP2pConfig 对象,然后从代表你想连接的设备的 WifiP2pDevice 中拷贝数据进去。再调用 connect 方法。然后项目需求是Pad端一定要作为group owner,这时候config.groupOwnerIntent = 15,增加这句话并不能一定作为group owner,只是一个建议。

 

         WifiP2pConfig config = new WifiP2pConfig();
                        config.deviceAddress = device.deviceAddress;
                        config.wps.setup = WpsInfo.PBC;


 为了兼容传统的Wifi设备,Wifi_Direct其实还存在另一种使用方 式,暂且称为兼容模式。兼容模式的特点在于,只需要担任GroupOwner的设备支持Wifi_Direct,而其他设备只需要支持传统的Wifi就可以了(个人觉得其实这种使用模式很像Android的便携热点功能)。

         操作流程为:
         1. 支持Wifi_Direct的设备创建group,WifiP2pManager.createGroup(),成为GroupOwner
         2.  其他设备扫描Wifi_Direct设备创建group后产生的Wifi热点并连接即可。
     
  
         兼容模式存在的一个问题是:因为作为group member的设备是使用Wifi硬件接入到group中,所以会导致member进行wifi 热点切换以及网络中断,可能对正在进行的网络操作造成影响,而group owner则不存在这个问题。另外,而WifiP2p配对的使用方式,WifiP2p和Wifi可以独立运作,相互不受影响。
          但是,兼容模式因为省去了扫描和配对的过程,所以建立连接的成功率明显提升,并且建立连接的速度要快不少(具体时间比较随机)。
          从个人的使用感觉来讲,这WifiP2p这套API接口高度的异步化,API都需要以回调的方式获取操作结果(包内interface比较多的原因就在于此)。更加麻烦的是,几个关键API(例如WifiP2pManager.connect)的回调获取到的结果仅仅是执行是否开始,真正的结果还得注册broadcast receiver,通过监听广播来获得,才能进行下一步操作。异步的设计提高了代码的逻辑复杂度。

 

7.连接信息获取要监听连接状态的变更,需要实现 WifiP2pManager.ConnectionInfoListener 接口,回调函数 onConnectionInfoAvailable将会在连接状态改变时通知。

 

回到广播接收器的onReceive方法中,修改监听WIFI_P2P_CONNECTION_CHANGED_ACTION的部分。收到该意图(Intent)时,调用requestConnectionInfo。这是一个异步的调用,所以结果会传给作为参数的连接信息监听器。


8.断连

removeGroup是移除群组,断连所有设备。

 

cancelConnect是取消连接状态为Invited的设备


一些问题:

如何获得WifiP2pGroupInfo,它有什么用?

WifiP2pManager.requestGroupInfo()函数,可以获取GroupInfo,较为有用的api有:
1. GroupInfo.getClientList()可以获得连接到group的member列表
2. GroupInfo.getNetWorkName()可以获得group的wifi热点名称(SSID)
3. GroupInfo.getPassphrase() 可以获得连接到wifi 热点的密码
 
如何防止配对产生的提示框?
在不修改framework的情况下,本人暂时为找到可行的方案。
这个提示狂是由系统提供的,具体表现视设备而定。nexus只在第一次配对的时候弹出,而A80每一次配对都会弹出。
但是,使用兼容模式使用Wifi_Direct是没有提示框的。
 
7.WifiP2pManager.discovePeers 仅仅返回附近有哪些设备开启了wifi p2p,而app的实际使用场景,往往希望寻找可以提供某些特定服务的设备。例如同一房间内,有A,B,C,D四台设备开启了wifi p2p,而A设备和B设备都安装了app1,C设备和D设备都安装了app2,使用者希望A设备能和B设备配对连接,而C设备与D设备连接,运行在A设备 上的app1如何识别它应该连接的是B设备,而非C、D设备呢?

为了支持更加个性化的设备发现,WifiP2pManager支持UPNP和DNS两种方式的设备(服务?)发现。
App可以通过WifiP2pManager.addLocalService来向周边的设备广播自己支持哪些服务。
也可以通过如下步骤实现发现这些服务:
1. 通过WifiP2pManager.addServiceRequest()添加服务请求
2. 通过WifiP2pManager.discoverService()开始服务发现
3. 通过WifiP2pManager.setDnsSdResponseListener()或者WifiP2pManager.setUpnpServiceResponseListener()监听服务内容。