`
test_angel
  • 浏览: 50059 次
  • 性别: Icon_minigender_2
  • 来自: 西安
社区版块
存档分类
最新评论

Wi-Fi直连

 
阅读更多
这几天看wifi直连的内容,对其中的api还不熟悉,总是看一个就去网上搜,好麻烦。所以果断的将下面文章(http://wiki.eoeandroid.com/Wi-Fi_Direct)给复制下来供参考使用。吐舌头

 

Wi-Fi 直连

Wi-Fi 直连技术允许已经配备了相应硬件并预装了Android 4.0(API level 14)或更后的操作系统的设备在不需要Wi-Fi中间热点的支持下通过Wi-Fi直接互联的技术。使用这些API,你可以发现和连接其他支持此技术的设 备,然后以距离远超蓝牙连接技术且速度更快的方式进行通信。这项技术对于一些多用户共享资料,比如多用户联机游戏或者相片分享等应用非常有用。

Wi-Fi直连技术的API包含以下主要部分:

  • 允许用户发现,请求然后连接对等设备的各种方法,定义在WifiP2pManager类中。
  • 允许用户定义收到调用WifiP2pManager类中方法成功或失败的通知的监听器。当用户调用WifiP2pManager类中的方法时,每一个方法都可以收到一个以参数形式传过来的特定监听。
  • 通知用户被Wi-Fi直连技术框架检测到的特定事件的意图,比如一个已丢掉的连接或者一个新的对等设备的发现等。

你经常会同时使用这三个主要组件的相关功能。例如,你可以为去调用android.net.wifi.p2p.WifiP2pManager.ActionListener) discoverPeers()方法而提供一个WifiP2pManager.ActionListener的监听器,这样以后你可以收到一个ActionListener.onSuccess()或者ActionListener.onFailure()方法的通知。一个WIFI_P2P_PEERS_CHANGED_ACTION意图同时也是当android.net.wifi.p2p.WifiP2pManager.ActionListener) discoverPeers()方法发现的对等设备列表发生改变时的一个广播。

API 概述

WifiP2pManager类提供了很多方法允许用户通过设备的Wi-Fi模块来进行交互,比如做一些如发现,连接其他对等设备的事情。下列的方法都是可以使用的: 表格1.Wi-Fi直连技术方法

方法名 详细描述

initialize()

通过Wi-Fi框架对应用来进行注册。这个方法必须在任何其他Wi-Fi直连方法使用之前调用。

connect()]

开始一个拥有特定设置的设备的点对点连接。

cancelConnect()

取消任何一个正在进行的点对点组的连接。

requestConnectInfo()

获取一个设备的连接信息。

createGroup()

以当前设备为组拥有者来创建一个点对点连接组。

removeGroup()

移除当前的点对点连接组。

requestGroupInfo()

获取点对点连接组的信息。

discoverPeers()

初始化对等设备的发现。

requestPeers()

获取当前发现的对等设备列表。

WifiP2pManager的方法可以让你在一个监听器里传递参数,这样Wi-fi直连框架就可以通知给你的窗体这个方法调用的状态。可以被使用的监听器接口和使用监听器的相应的WifiP2pManager的方法的调用都将在下面这张表中有所描述:

表格 2. Wi-Fi直连监听器方法

监听器接口 相关联的方法

WifiP2pManager.ActionListener

connect(), cancelConnect(), createGroup(), removeGroup(), and discoverPeers()

WifiP2pManager.ChannelListener

initialize()

WifiP2pManager.ConnectionInfoListener

requestConnectInfo()

WifiP2pManager.GroupInfoListener

requestGroupInfo()

WifiP2pManager.PeerListListener

requestPeers()

Wi-Fi直连技术的API定义了一些当特定的Wi-Fi直连事件发生时作为广播的意图,比如说当一个新的对等设备被发现,或者一个设备的Wi-Fi状态的改变。你可以在你的应用里通过创建一个处理这些意图的广播接收器来注册去接收这些意图。

Table 3. Wi-Fi 直连意图

意图名称 详细描述

WIFI_P2P_CONNECTION_CHANGED_ACTION

当设备的Wi-Fi连接信息状态改变时候进行广播。

WIFI_P2P_PEERS_CHANGED_ACTION

当调用discoverPeers()方法的时候进行广播。在你的应用里处理此意图时,你通常会调用requestPeers()去获得对等设备列表的更新。

WIFI_P2P_STATE_CHANGED_ACTION

当设备的Wi-Fi 直连功能打开或关闭时进行广播。

WIFI_P2P_THIS_DEVICE_CHANGED_ACTION

当设备的详细信息改变的时候进行广播,比如设备的名称

创建一个Wi-Fi直连意图使用的广播接收器

一个广播接收器允许你接收由android系统发布的意图广播,这样你的应用就可以对那些你感兴趣的事件作出响应。创建一个基本的Wi-Fi直连意图使用的广播接收器的步骤如下:

1.创建一个继承自BroadcastReceiver的类。对于类的构造,一般最常用的就是以WifiP2pManager, WifiP2pManager.Channel作为参数,同时这个广播接收器对应的窗体也将被注册进来。这个广播接收器可以像窗体发送更新或者在需要的时 候可以访问Wi-Fi硬件或通信通道。

2.在广播接收器里,处理onReceive()方法里你感兴趣的意图。执行接收到的意图的任何需要的动作。比如,广播接收器接收到一个 WIFI_P2P_PEERS_CHANGED_ACTION的意图,你就要调用requestPeers()方法去获得当前发现的对等设备列表。

下面的代码展示了怎样去创建一个典型的广播接收器。广播接收器接收一个WifiP2pManager对象和一个窗体对象作为参数然后利用这两个类去处理接收到的意图的特定的动作需求。

 
/**
 * A BroadcastReceiver that notifies of important Wi-Fi p2p events.
 */
public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
 
    private WifiP2pManager manager;
    private Channel channel;
    private MyWiFiActivity activity;
 
    public WiFiDirectBroadcastReceiver(WifiP2pManager manager, Channel channel,
            MyWifiActivity activity) {
        super();
        this.manager = manager;
        this.channel = channel;
        this.activity = activity;
    }
 
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
 
        if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
            // Check to see if Wi-Fi is enabled and notify appropriate activity
        } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
            // Call WifiP2pManager.requestPeers() to get a list of current peers
        } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
            // Respond to new connection or disconnections
        } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
            // Respond to this device's wifi state changing
        }
    }
}
 

创建一个Wi-Fi直连的应用

创建一个Wi-Fi直连的应用包括创建和注册一个广播接收器,发现其他设备,连接其他设备,然后传输数据等步骤。接下来的几个部分描述了怎么去做这些工作。

初始化设置

在使用Wi-Fi直连的API之前,你必须确保你的应用可以访问设备的硬件并且你的设备要支持Wi-Fi直连的通讯协议。如果Wi-Fi直连技术是 支持的,你可以获得一个WifiP2pManager的实例对象,然后创建并注册你的广播接收器,然后开始使用Wi-Fi直连的API方法。

1.为设备的Wi-Fi硬件获取权限并在Android的清单文件中声明你的应用正确使用的最低SDK版本:

 
<uses-sdk android:minSdkVersion="14" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 
 

2.检查设备是否支持Wi-Fi直连技术。一种好的解决办法是当你的广播接收器接收到一个WIFI_P2P_STATE_CHANGED_ACTION意图。通知你的窗体Wi-Fi直连的状态和相应的反应。

 
@Override
public void onReceive(Context context, Intent intent) {
    ...
    String action = intent.getAction();
    if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
        int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
        if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
            // Wifi Direct is enabled
        } else {
            // Wi-Fi Direct is not enabled
        }
    }
    ...
}
 
 

3.在你的窗体的onCreate()方法里,获得一个WifiP2pManager的实例并调用initialize()方法通过Wi-Fi直连 框架去注册你的应用。这个方法返回一个WifiP2pManager.Channel对象,是被用来连接你的应用和Wi-Fi直连框架的。你应该再创建一 个以WifiP2pManager和WifiP2pManager.Channel为参数且关联你的窗体的广播接收器的实例。这样你的广播接收器就可以接 收到你感兴趣的事件去通知你的窗体并更新它。它还可以让你在需要的时候操纵设备的Wi-Fi状态。

 
WifiP2pManager mManager;
Channel mChannel;
BroadcastReceiver mReceiver;
...
@Override
protected void onCreate(Bundle savedInstanceState){
    ...
    mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
    mChannel = mManager.initialize(this, getMainLooper(), null);
    mReceiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
    ...
}
 

4.创建一个意图过滤器并把它添加在你的广播接收器需要处理的意图上。

 
IntentFilter mIntentFilter;
...
@Override
protected void onCreate(Bundle savedInstanceState){
    ...
    mIntentFilter = new IntentFilter();
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
    mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
    ...
}
 

5.注册你的广播接收器在窗体的onResume()方法,解除注册在onPause()方法中。

 
/* register the broadcast receiver with the intent values to be matched */
@Override
protected void onResume() {
    super.onResume();
    registerReceiver(mReceiver, mIntentFilter);
}
/* unregister the broadcast receiver */
@Override
protected void onPause() {
    super.onPause();
    unregisterReceiver(mReceiver);
}
 

当你获取到一个WifiP2pManager.Channel对象并且设置好你的广播接收器时,你的应用就可以调用Wi-Fi直连的方法并且可以接收Wi-Fi直连的意图。

你可以现在就通过调用WifiP2pManager中的方法取实现你的应用体验Wi-Fi直连技术的特性了。下面的章节描述了怎样去实现一些常用的操作,比如说发现其他设备和连接它们。

 

发现对等设备

要发现可以使用并连接的对等设备,调用discoverPeers()方法去检测在范围内的可使用设备。这个方法的调用是异步的同时如果你创建了一 个WifiP2pManager.ActionListener监听器的话你会通过onSuccess()或者onFailure()方法收到发现成功或 失败的消息。onSuccess()方法只能通知你发现的过程是否成功而不能提供任何关于发现设备的信息:

 
manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
    @Override
    public void onSuccess() {
        ...
    }
 
    @Override
    public void onFailure(int reasonCode) {
        ...
    }
});
 

如果发现过程成功且检测到了对等设备,系统将会广播出一个WIFI_P2P_PEERS_CHANGED_ACTION意图,这样你就可以利用广播 监听器监听并获得发现设备的列表。当你的应用接收到WIFI_P2P_PEERS_CHANGED_ACTION意图时,你就可以调用 requestPeers()方法来获取发现设备的列表,代码如下:

 
PeerListListener myPeerListListener;
...
if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
 
    // request available peers from the wifi p2p manager. This is an
    // asynchronous call and the calling activity is notified with a
    // callback on PeerListListener.onPeersAvailable()
    if (manager != null) {
        manager.requestPeers(channel, myPeerListListener);
    }
}
 

连接到设备

当你已经找到你要连接的设备在获得发现设备列表之后,调用connect()方法去连接指定设备。这个方法的调用需要一个包含待连接设备信息的 WifiP2pConfig对象。你可以通过WifiP2pManager.ActionListener接收到连接是否成功的通知。下面的代码展示了怎 样去连接一个想得到的连接:

 
//obtain a peer from the WifiP2pDeviceList
WifiP2pDevice device;
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
manager.connect(channel, config, new ActionListener() {
 
    @Override
    public void onSuccess() {
        //success logic
    }
 
    @Override
    public void onFailure(int reason) {
        //failure logic
    }
});
 

数据传输

一旦连接已经建立,你可以通过套接字来进行数据的传输。基本的数据传输步骤如下:

1.创建一个ServerSocket对象。这个服务端套接字对象等待一个来自指定地址和端口的客户端的连接且阻塞线程直到连接发生,所以把它建立在一个后台线程里。

2.创建一个客户端Socket.这个客户端套接字对象使用指定ip地址和端口去连接服务端设备。

3.从客户端给服务端发送数据。当客户端成功连接服务端设备后,你可以通过字节流从客户端给服务端发送数据。

4.服务端等待客户端的连接(使用accept()方法)。这个调用阻塞服务端线程直到客户端连接上,所以叫这个过程一个新的线程。当连接建立时,服务端可以接受来自客户端的数据。执行关于数据的任何动作,比如保存数据或者展示给用户。

下来的例子,从Wi-Fi直连示例改编而来,展示了怎样去创建服务端和客户端的连接和通信,并且使用一个客户端到服务端的服务来传输了一张JPEG图像。如需要得到一个完整的商业例子,请移步Wi-Fi直连示例。

 
public static class FileServerAsyncTask extends AsyncTask {
 
    private Context context;
    private TextView statusText;
 
    public FileServerAsyncTask(Context context, View statusText) {
        this.context = context;
        this.statusText = (TextView) statusText;
    }
 
    @Override
    protected String doInBackground(Void... params) {
        try {
 
            /**
             * Create a server socket and wait for client connections. This
             * call blocks until a connection is accepted from a client
             */
            ServerSocket serverSocket = new ServerSocket(8888);
            Socket client = serverSocket.accept();
 
            /**
             * If this code is reached, a client has connected and transferred data
             * Save the input stream from the client as a JPEG file
             */
            final File f = new File(Environment.getExternalStorageDirectory() + "/"
                    + context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
                    + ".jpg");
 
            File dirs = new File(f.getParent());
            if (!dirs.exists())
                dirs.mkdirs();
            f.createNewFile();
            InputStream inputstream = client.getInputStream();
            copyFile(inputstream, new FileOutputStream(f));
            serverSocket.close();
            return f.getAbsolutePath();
        } catch (IOException e) {
            Log.e(WiFiDirectActivity.TAG, e.getMessage());
            return null;
        }
    }
 
    /**
     * Start activity that can handle the JPEG image
     */
    @Override
    protected void onPostExecute(String result) {
        if (result != null) {
            statusText.setText("File copied - " + result);
            Intent intent = new Intent();
            intent.setAction(android.content.Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.parse("file://" + result), "image/*");
            context.startActivity(intent);
        }
    }
}
 

在客户端,使用客户端套接字连接服务端套接字并传输数据。这个例子从客户端的文件系统里传输了一张JPEG的图像到服务端。

 
Context context = this.getApplicationContext();
String host;
int port;
int len;
Socket socket = new Socket();
byte buf[]  = new byte[1024];
...
try {
    /**
     * Create a client socket with the host,
     * port, and timeout information.
     */
    socket.bind(null);
    socket.connect((new InetSocketAddress(host, port)), 500);
 
    /**
     * Create a byte stream from a JPEG file and pipe it to the output stream
     * of the socket. This data will be retrieved by the server device.
     */
    OutputStream outputStream = socket.getOutputStream();
    ContentResolver cr = context.getContentResolver();
    InputStream inputStream = null;
    inputStream = cr.openInputStream(Uri.parse("path/to/picture.jpg"));
    while ((len = inputStream.read(buf)) != -1) {
        outputStream.write(buf, 0, len);
    }
    outputStream.close();
    inputStream.close();
} catch (FileNotFoundException e) {
    //catch logic
} catch (IOException e) {
    //catch logic
}
 
/**
 * Clean up any open sockets when done
 * transferring or if an exception occurred.
 */
finally {
    if (socket != null) {
        if (socket.isConnected()) {
            try {
                socket.close();
            } catch (IOException e) {
                //catch logic
            }
        }
    }
}
 

 

分享到:
评论

相关推荐

    Iphone Wi-Fi Direct wiif直连解决方案.pdf

    Wi-Fi直连大战蓝牙4.0

    蓝牙曾经是无线设备之间直接连接的事实标准,今年7月,负责蓝牙标准制定的蓝牙特别兴趣小组发布了最新的蓝牙4.0标准,但最近出了个强大的竞争对手,本月25日,Wi-Fi联盟开始正式认证Wi-Fi直连设备,从此拉开了蓝牙...

    Wi-Fi直连发布渗透智能电网

    在没有Wi-Fi网络和互联网的地方,用户也可轻松实现各种终端间的互联,从而开启丰富的应用世界,这就是Wi-Fi直连技术的魅力所在。与此同时,Wi-Fi已经超越了传统家庭网络的范围,扩展至能源管理应用,以及物联网涉及...

    ios Esp8266 乐鑫芯片Wi-Fi模式 及 直连模式Demo

    ios Esp8266 乐鑫芯片Wi-Fi模式 及 直连模式Demo 直连模式进入页面会自动连接IP和端口号,数据解析 自行修改

    WifiDirect.7z

    Wi-Fi直连(英语:Wi-Fi Direct),之前曾被称为Wi-Fi 点对点(Wi-Fi Peer-to-Peer),是一套软件协定,让 wifi 设备可以不必通过无线网络基地台(Access Point),以点对点的方式,直接与另一个 wifi 设备连接,...

    WIFI模块RF-WM-3200介绍.

    RF-WM-3200B1模块是RF-Star全新推出的一款嵌入式Wi-Fi模块,该模块采用...模块支持802.11 b/g/n无线标准,支持Station,AP和Wi-Fi直连模式。另外模块硬件还包含了陶瓷天线、IPEX座子和天线焊盘等3种天线方式可供选择。

    WIFI DIRECT demo

    Wi-Fi直连技术的API包含以下主要部分: 允许用户发现,请求然后连接对等设备的各种方法,定义在WifiP2pManager类中。 允许用户定义收到调用WifiP2pManager类中方法成功或失败的通知的监听器。当用户调用WifiP2...

    无线网络 随身携带--Wi-Fi直连面面观[图]

    Wi-Fi技术提供了一种便捷经济的无线接入方式,但是受制于热点有限的问题,始终有不能随时随地应用的遗

    TI 3200wifi模块联网操作说明

    RF-WM-3200B1模块是RF-Star全新推出...模块支持802.11 b/g/n无线标准,支持Station,AP和Wi-Fi直连模式。另外模块硬件还包含了陶瓷天线、IPEX座子和天线焊盘等3种天线方式可供选择,支持AT命令模式和串口数据透传模式。

    信驰达WIFI3200使用手册 用户指南说明书

    RF-WM-3200B1模块是RF-Star全新推出...模块支持802.11 b/g/n无线标准,支持Station,AP和Wi-Fi直连模式。另外模块硬件还包含了陶瓷天线、IPEX座子和天线焊盘等3种天线方式可供选择,支持AT命令模式和串口数据透传模式。

    iOS11实现App内自动连接Wi-Fi的方法

    给智能设备配置网络,需要直连智能设备发射的Wi-Fi 目前技术: iOS11后苹果提供 NEHotspotConfigurationManager 类直连周边Wi-Fi,iOS11前只能跳转到系统设置界面手动连接Wi-Fi 步骤 给开发者中心给 Appid 配置...

    Iphone Wi-Fi Direct wiif直连解决方案.docx

    嵌入式系统/ARM技术中的车载Wi-Fi安全问题引发担忧

    当然,无论是Wi-Fi还是直连,汽车上网是近几年才出现在市场中的新景观。  不过,美国研究人员对汽车的控制系统近日实施了一系列攻击测试后得出结论说,面对黑客的恶意攻击,汽车电脑也难逃一劫。研究人员表示,汽车...

    车载Wi-Fi引发新担忧 安全问题不容忽视

    网络在人们生活中的分量已经有目共睹,对于很多开车的人来说,要是能在车上享受到Wi-Fi的便利那就更好了,如此一来驾驶员就可以在停车场等人的...当然,无论是Wi-Fi还是直连,汽车上网是近几年才出现在市场中的新景观。

    wifi_shoot p2p

    》Wi-Fi Direct是WiFi联盟发布的一套允许无线网络中的设备无需通过无线路由器即可相互直连的标准,允许无线设备以点对点形式互连,不过在传输速度与传输距离方面则比蓝牙有大幅提升,主要对手是蓝牙3.0协议。...

    基于嵌入式的无线智能家居网关设计方案

    摘要: 针对传统智能家居系统中多种无线通信技术之间互联的困扰,设计了一个新的两种无线通信技术直连的智能家居网关。该网关以ARM920T 嵌入式处理器S3C2440A 为,ARM Linux 为实时操作系统,采用新兴的Zigbee 与Wi-...

    TestWiFiDirect

    在底部(通常)会有一个 Wi-Fi 直连选项。安装签出或下载代码 zip 并导入到 Android Studio。 在两台设备上运行应用程序。 如果设备已连接到任何 wi-fi 网络,请断开连接。 在应用程序运行时,访问菜单并单击“发现...

    三星Xpress M2836DW打印机驱动 v3.12.75.04.10 官方最新版

    此款驱动是三星Xpress M2836DW打印机驱动官方最新版,适用于XP/2003以上的Windows和服务器操作...M2836DW拥有先进的NFC(近场通讯)、Wi-Fi直连、谷歌云打印技术,并且具有广泛的兼容性,只需轻轻一触,即,欢迎下载体验

    基于Qualcomm A7 Linux+ CSR6030的车载中控方案-电路方案

    此外,CSR6030A11符合Wi-Fi Direct 标准,这就意味着它可以连接到其他具备Wi-Fi Certified 认证的 Wi-Fi Direct 设备上,无需依靠热点可以进行直连。这些功能为系统设计者提供了更大的灵活性,使其可以在快速变化的...

    android wifi direct Demo

    wifi直连的工作流程

Global site tag (gtag.js) - Google Analytics