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

目录

[隐藏

使用Wi-Fi Direct连接 - Connecting with Wi-Fi Direct

Wi-Fi Direct™的API允许应用程序不通过网络或热点,直接与周围的设备进行连接。应用程序可以迅速地查找附近的设备,交换信息。并且与蓝牙相比,Wi-Fi Direct的通讯范围更大。 这节课将向你介绍,如何使用Wi-Fi Direct查找附近的设备,并与之连接。

设置应用程序权限 - Set Up Application Permissions

使用Wi-Fi Direct,需要向你的清单文件添加 CHANGE_WIFI_STATEACCESS_WIFI_STATE 和 INTERNET 权限。Wi-Fi Direct不需要因特网连接,但需要使用标准Java套接字,而套接字需要 INTERNET 权限,因此,你需要有以下的权限才可以使用Wi-Fi Direct。

<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"/>
...

创建一个广播接收器和对等网络管理器 - Set Up a Broadcast Receiver and Peer-to-Peer Manager

使用Wi-Fi Direct,你需要监听广播意图(Intents)来获知某个特定事件的发生。在你的应用程序中,初始化一个 IntentFilter,并让它监听以下动作:

WIFI_P2P_STATE_CHANGED_ACTION

表明Wi-Fi对等网络(P2P)是否已经启用

WIFI_P2P_PEERS_CHANGED_ACTION

表明可用的对等点的列表发生了改变

WIFI_P2P_CONNECTION_CHANGED_ACTION

表示Wi-Fi对等网络的连接状态发生了改变

WIFI_P2P_THIS_DEVICE_CHANGED_ACTION

表示该设备的配置信息发生了改变

private final IntentFilter intentFilter = new IntentFilter();
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); //表示Wi-Fi对等网络状态发生了改变
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); //表示可用的对等点的列表发生了改变
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); //表示Wi-Fi对等网络的连接状态发生了改变
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); //设备配置信息发生了改变
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); ...
}

在 onCreate() 方法的最后,获得了 WifiP2pManager 的一个实例,并调用了他的 initialize() 方法。这个方法返回一个 WifiP2pManager.Channel 对象。稍后会用它把你的应用程序连接到Wi-Fi Direct框架中。

@Override

Channel mChannel;

public void onCreate(Bundle savedInstanceState) {
....
mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(this, getMainLooper(), null);
}

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

@Override
public void onReceive(Context context, Intent intent) {
  String action = intent.getAction();
  if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {     //确定Wi-Fi Direct模式是否已经启用,并提醒Activity。
    int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
    if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
      activity.setIsWifiP2pEnabled(true);
    } else {
      activity.setIsWifiP2pEnabled(false);
    }
  } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {     //对等点列表已经改变!我们可能需要对此做出处理。   } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {     //连接状态已经改变!我们可能需要对此做出处理。   } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
    DeviceListFragment fragment = (DeviceListFragment) activity.getFragmentManager()
          .findFragmentById(R.id.frag_list);
    fragment.updateThisDevice((WifiP2pDevice) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE));   }
}

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

  /*注册一个与意图(Intent)值匹配的广播接收器*/
@Override
public void onResume() {
super.onResume();
receiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
registerReceiver(receiver, intentFilter);
} @Override
public void onPause() {
super.onPause();
unregisterReceiver(receiver);
}

初始化对等点的搜索 - Initiate Peer Discovery

使用Wi-Fi Direct搜索附近的设备,需要调用 discoverPeers()方法。其参数如下:

  • WifiP2pManager.Channel 是在你初始化对等网络的mManager时收到的。
  • WifiP2pManager.ActionListener 的一个实例,实现了系统在查找成功或失败时会调用的方法。 
    mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
    
            @Override
    public void onSuccess() {
    //查找初始化成功时的处理写在这里。 //实际上并没有发现任何服务,所以该方法可以置空。
    //对等点搜索的代码在onReceive方法中,详见下文。
    } @Override
    public void onFailure(int reasonCode) {
    //查找初始化失败时的处理写在这里。
    //警告用户出错了。
    }
    });

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

获取对等点列表 - Fetch the List of Peers

下面添加代码,获取对等点的列表并进行处理。首先实现 WifiP2pManager.PeerListListener 接口,它提供了Wi-Fi Direct检测到的对等点信息。参见下面的代码片段。

private List peers = new ArrayList();
... private PeerListListener peerListListener = new PeerListListener() {
@Override
public void onPeersAvailable(WifiP2pDeviceList peerList) { //旧的不去,新的不来
peers.clear();
peers.addAll(peerList.getDeviceList()); //如果AdapterView可以处理该数据,则把变更通知它。比如,如果你有可用对等点的ListView,那就发起一次更新。
((WiFiPeerListAdapter) getListAdapter()).notifyDataSetChanged();
if (peers.size() == 0) {
Log.d(WiFiDirectActivity.TAG, "No devices found");
return;
}
}
}

现在,修改你的广播接收器的 onReceive() 方法,以便在收到一个带有 WIFI_P2P_PEERS_CHANGED_ACTION 动作的意图(Intent)时调用 requestPeers()方法。你得想办法把这个监听器传给接收器。其中一个方法是,将它作为一个参数传递给广播接收器的构造函数。

public void onReceive(Context context, Intent intent) {
...
else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) { //从Wi-Fi P2P管理器中请求可用的对等点。
//这是个异步的调用,
//并且,调用行为是通过PeerListListener.onPeersAvailable()上的一个回调函数来通知的。
if (mManager != null) {
mManager.requestPeers(mChannel, peerListener);
}
Log.d(WiFiDirectActivity.TAG, "P2P peers changed");
}...
}

至此,带有 WIFI_P2P_PEERS_CHANGED_ACTION 动作的意图(Intent)将会发起一个更新对等点列表的请求。

连接一个对等点 - Connect to a Peer

为了连接一个对等点,需要先创建一个新的 WifiP2pConfig 对象,然后从代表你想连接的设备的 WifiP2pDevice 中拷贝数据进去。再调用 connect() 方法。

@Override
public void connect() {   //使用在网络上找到的第一个设备。
  WifiP2pDevice device = peers.get(0);   WifiP2pConfig config = new WifiP2pConfig();
  config.deviceAddress = device.deviceAddress;
  config.wps.setup = WpsInfo.PBC;   mManager.connect(mChannel, config, new ActionListener() {     @Override
    public void onSuccess() {
      // WiFiDirectBroadcastReceiver将会通知我们。现在可以先忽略。
    }     @Override
    public void onFailure(int reason) {
      Toast.makeText(WiFiDirectActivity.this, "Connect failed. Retry.",
        Toast.LENGTH_SHORT).show();
      }
  });
}

在这个代码片段中实现的 WifiP2pManager.ActionListener 只会在初始化成功或失败时通知你。要监听连接状态的变更,需要实现 WifiP2pManager.ConnectionInfoListener 接口。其回调函数 onConnectionInfoAvailable()将会在连接状态改变时通知你。对于多个设备连接一个设备的情况(比如,多于3个玩家的游戏,或者聊天软件),其中一个设备将会被指定为“群主”。

@Override
public void onConnectionInfoAvailable(final WifiP2pInfo info) {   // InetAddress在WifiP2pInfo结构体中。
  InetAddress groupOwnerAddress = info.groupOwnerAddress.getHostAddress());   //组群协商后,就可以确定群主。
  if (info.groupFormed && info.isGroupOwner) {
//针对群主做某些任务。
//一种常用的做法是,创建一个服务器线程并接收连接请求。
  } else if (info.groupFormed) {
//其他设备都作为客户端。在这种情况下,你会希望创建一个客户端线程来连接群主。
  }
}

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

...
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) { if (mManager == null) {
return;
} NetworkInfo networkInfo = (NetworkInfo) intent
.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO); if (networkInfo.isConnected()) { //我们连上了其他的设备,请求连接信息,以找到群主的IP。
mManager.requestConnectionInfo(mChannel, connectionListener);
}
...

连接无线设备——与Wi-Fi直接连接的更多相关文章

  1. 双系统下(Ubuntu + win7)windows 无法连接无线网络

    双系统下(Ubuntu + win7)windows 无法连接无线网络 今天开机登录win7,突然发现无法使用无线网络(WiFi信号标志有个大红叉),于是查看设备驱动,一切正常,这就奇怪了:用Wind ...

  2. adb通过wifi连接android设备

    问题背景 近期的项目测试中,需要将移动设备与厂商机器进行usb连接视频传输(投屏).测试过程中需要定位问题,经常需要查看实时日志,移动设备已经和厂商机器usb连接投屏,无法用usb连接到PC,那么有什 ...

  3. Wi-Fi无线网络(WPA2加密)快速破解 ——某公司无线设备安全隐患报告

    Wi-Fi无线网络(WPA2加密)快速破解 --某公司无线设备安全隐患报告 评估人:阿牛 2013年12月12日 文件夹 一. 导言 2 二. 背景 2 三. 无线产品应当採取的安全策略 3 四. 存 ...

  4. linux开机自动连接无线网络

           1.右击无线网络图标的“编辑连接”. 2.在“无线”选项卡里,选择“编辑”. 3.在“无线安全性”选项卡里,输入无线密匙,并选中左下角的“对所有用户可      用”的选项点击应用,会提 ...

  5. 记在centos中连接无线网络的一次过程

    1. 首先, 你的系统要能驱动无限网卡, 要是人品好的话, 系统已经自带了你的网卡的驱动程序. 不然就要先搞定无线网卡的驱动再说. 不然后面的步骤也就没必要了. 2. 看一下你的无线网卡叫什么: iw ...

  6. C#编程使用Managed Wifi API连接无线SSID

    C#编程使用Managed Wifi API连接无线SSIDhttp://www.2cto.com/kf/201307/227623.html Managed Wifi API - Homehttp: ...

  7. ubuntu16.04无法连接无线的问题解决方式以及QQ的安装

    0x01 首先我是安装了win10与ubuntu16.04的双系统,不过遇到的问题有启动项与无线连接的问题,今天说一下联网的问题. 连接宽带是正常的,只需要操作sudo pppoeconf 这条命令即 ...

  8. 【转】ubuntu连接android设备(附最简单方法)

    原文网址:http://blog.csdn.net/maosidiaoxian/article/details/22661725 在ubuntu下连接android设备,虽然不用像windows那样安 ...

  9. ubuntu连接android设备(附最简单方法)

    在ubuntu下连接android设备,虽然不用像windows那样安装驱动,然而却会遇见一个错误:输入adb shell,会提示insufficient permissions for device ...

随机推荐

  1. WPF 面试题及答案(二)

    一 · WPF中什么是样式? 首先明白WPF中样式属于资源中重要的一种. 同时样式也是属性值的集合,能被应用到一个合适的元素中,或者说能将一组属性应用到多个元素. WPF中样式可以设置任何依赖属性. ...

  2. 头部固定下面滑动&&获取手机屏高

    height(){ //获取屏高 let phone_height = document.documentElement.clientHeight; let group = this.refs.sea ...

  3. wampserver2.6下UCenter1.6.0与UCenter Home2.0整合安装

    上一篇文章,我们已经安装了,ucenter1.6.0,所以此文介绍独立安装ucenter1.6.0与ucenter home2.0的整合安装. 1,)从官网下载UCenter_Home_2.0_SC_ ...

  4. NABCD模式

    各位用户:       我们的“昵妆”是为了帮助不会化妆的用户解决困难, 他们需要有适合他们的优质的化妆品和 正确的视频或者化妆师来指导他们,但是现有的方案并没有很好地解决这些需求,我们有独特的办法, ...

  5. Leetcode: Convert a Number to Hexadecimal

    Given an integer, write an algorithm to convert it to hexadecimal. For negative integer, two's compl ...

  6. Python和Ruby抓取网页时的中文乱码问题(在Eclipse和Apatana Studio下均是这种解决方法

    Python抓取中文网页乱码 :Eclipse+pydev2.2+python2.7  :Apatana Studio3+ pydev2.2+python2.7      run时设置 run--&g ...

  7. 封装mysql类

    类: <?phpheader("content-type:text/html;charset=utf-8");//封装一个类/*掌握满足单例模式的必要条件(1)私有的构造方法 ...

  8. paper 65 :尺度不变特征变换匹配算法[转载]

    尺度不变特征变换匹配算法 对于初学者,从David G.Lowe的论文到实现,有许多鸿沟,本文帮你跨越.1.SIFT综述 尺度不变特征转换(Scale-invariant feature transf ...

  9. angular 依赖注入

    依赖注入    依赖注入(DI)是一个经典的设计模式, 主要是用来处理组件如何获得依赖的问题.关于DI,推荐阅读Martin Flower的文章(http://martinfowler.com/art ...

  10. zw版_Halcon-delphi系列教程_卫星航拍精确打击目标自动识别

    <zw版·Halcon-delphi系列原创教程> 卫星航拍精确打击目标自动识别 这几天,俄罗斯空军在叙利亚大显神威,美军有意见了,说俄罗斯是狂轰滥炸,不是精确打击.      不过,战斗 ...