`

Connecting with Wi-Fi Direct

 
阅读更多
Connecting with Wi-Fi Direct

     Wi-Fi Direct™ APIs允许应用连接周围的设备,而不用通过网络或者热点,点对点直接连接。应用可以快速的发现周围设备并与之交互,而有效作用距离大于蓝牙。

     以下内容关于如何通过Wi-Fi Direct™发现和连接周围设备:

第一步:权限问题 Set Up Application Permissions

在manifest里添加三个权限:

CHANGE_WIFI_STATE,

ACCESS_WIFI_STATE,

INTERNET 。

Wi-Fi Direct™不需要网络,但是需要java socket,而java socket需要INTERNET 权限。

<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™,需要监听(broadcast intents)广播intent,当有特定的事件发生时,你的应用就会觉察到。

在app里实例化一个IntentFilter对象出来,将其设置为监听以下内容:

WIFI_P2P_STATE_CHANGED_ACTION
Indicates whether Wi-Fi Peer-To-Peer (P2P) is enabled----P2P功能是否打开
WIFI_P2P_PEERS_CHANGED_ACTION
Indicates that the available peer list has changed.----可连接peer改变
WIFI_P2P_CONNECTION_CHANGED_ACTION
Indicates the state of Wi-Fi P2P connectivity has changed.----P2P连接状态改变
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION
Indicates this device's configuration details have changed.----设备设置改变

private final IntentFilterintentFilter = new IntentFilter();
...
@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    //  Indicates a change in the Wi-Fi Peer-to-Peer status.
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);

    // Indicates a change in the list of available peers.
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);

    // Indicates the state of Wi-Fi P2P connectivity has changed.
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);

    // Indicates this device's details have changed.
    intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);

    ...
}

     在onCreate()方法最后,取得一个WifiP2pManager实例,调用它的initialize()方法,这个方法返回一个WifiP2pManager.Channel对象,这个后面用来连接app和Wi-Fi Direct Framework。

@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()方法里,增加condition条件来处理各种P2P状态的改变。

@Override
public void onReceive(Context context, Intent intent) {

        String action = intent.getAction();     //获取接收的intent里的action

        //以下进行判断,对各种不同的P2P状态改变,执行不同的代码
     if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
            // 检查 Wifi Direct模式是否开启
            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)) {

            // The peer list has changed!  We should probably do something about that.
          }

     else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {

            // Connection state changed!  We should probably do something about that.
          }

      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));

        }
    }

      最后,当你 主activity 激活以后,添加代码在onResume()方法里注册 intent filter 和 broadcast receiver 。当你的activity paused的时候,在onPause()方法里对它们解除注册。

    @Override

    public void onResume() {
        super.onResume();
        receiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
        registerReceiver(receiver, intentFilter);
    }

    @Override
    public void onPause() {
        super.onPause();      //调用父类方法
        unregisterReceiver(receiver);   //添加新的内容,解除注册
    }

第三步:开始peer发现   Initiate Peer Discovery

调用discoverPeers()方法,来发现周围的设备。这个方法需要2个参数:

1. WifiP2pManager.Channel

2. WifiP2pManager.ActionListener 的一个新的实现

第一个参数是一个对象,第二个参数是内部类对象

mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {

        @Override
        public void onSuccess() {
            // Code for when the discovery initiation is successful goes here.
            // No services have actually been discovered yet, so this method
            // can often be left blank.  Code for peer discovery goes in the
            // onReceive method, detailed below.
        }

        @Override
        public void onFailure(int reasonCode) {
            // Code for when the discovery initiation fails goes here.
            // Alert the user that something went wrong.
        }
});

这只是启动peer discovery,方法discoverPeers()开始了发现线程,然后马上返回。如果peer discovery线程成功启动,系统就会注意到。发现一直持续直到建立连接或者建立一个P2P group。



第四步:获取peer 列表 Fetch the List of Peers

首先实现WifiP2pManager.PeerListListener接口,这个接口提供了发现的peer的信息。

   private List peers = new ArrayList(); //装peer的list
    ...

    private PeerListListener peerListListener = new PeerListListener() {
        @Override
        public void onPeersAvailable(WifiP2pDeviceList peerList) {

            // Out with the old, in with the new.
            peers.clear();   //清空list,刷新
            peers.addAll(peerList.getDeviceList());

            // If an AdapterView is backed by this data, notify it
            // of the change.  For instance, if you have a ListView of available
            // peers, trigger an update.
            ((WiFiPeerListAdapter) getListAdapter()).notifyDataSetChanged();

            //如果peers.size()=0,则没有发现peer
            if (peers.size() == 0) {
                Log.d(WiFiDirectActivity.TAG, "No devices found");
                return;
            }
        }
    }



修改broadcast receiver的onReceive()方法,当接收到一个action包含WIFI_P2P_PEERS_CHANGED_ACTION的Intent的时候,调用requestPeers()方法,

需要把监听器传入接收器,方法之一就是把listener传入broadcast receiver构造器。



public void onReceive(Context context, Intent intent) {
    ...
    else 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 (mManager != null) {
            mManager.requestPeers(mChannel, peerListener);
        }
        Log.d(WiFiDirectActivity.TAG, "P2P peers changed");
    }...
}

    这样的话,一个intent的action是 WIFI_P2P_PEERS_CHANGED_ACTION 的时候,就会触发更新peer list的请求。

第五步:连接peer:Connect to a Peer

     要连接peer,就要new一个新的 WifiP2pConfig对象,并把想连接的peer的信息写入,最后调用 connect()方法。

  @Override
    public void connect() {
        // Picking the first device found on the network.
        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 will notify us. Ignore for now.
            }

            @Override
            public void onFailure(int reason) {
                Toast.makeText(WiFiDirectActivity.this, "Connect failed. Retry.",
                        Toast.LENGTH_SHORT).show();
            }
        });
    }

     WifiP2pManager.ActionListener只是负责通知peer initiation是否成功,要监听P2P状态改变的话,就要实现WifiP2pManager.ConnectionInfoListener,它的onConnectionInfoAvailable()回调方法会在P2P状态改变时做出反应。在多个设备需要连接同一个设备的情况下,有一个设备会被指定为“group owner“。

   @Override

    public void onConnectionInfoAvailable(final WifiP2pInfo info) {

        // InetAddress from WifiP2pInfo struct.

        InetAddress groupOwnerAddress = info.groupOwnerAddress.getHostAddress());


        // After the group negotiation, we can determine the group owner.

        if (info.groupFormed && info.isGroupOwner) {

            // Do whatever tasks are specific to the group owner.

            // One common case is creating a server thread and accepting

            // incoming connections.

        } else if (info.groupFormed) {

            // The other device acts as the client. In this case,

            // you'll want to create a client thread that connects to the group

            // owner.

        }

    }

返回到 broadcast receiver里的 onReceive()方法,修改下, 接收到WIFI_P2P_CONNECTION_CHANGED_ACTION 这个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()) {

                // We are connected with the other device, request connection

                // info to find group owner IP

                mManager.requestConnectionInfo(mChannel, connectionListener);

            }

From: http://blog.sina.com.cn/s/blog_819100560101a86s.html
LINUX\android\development\samples\WiFiDirectDemo
android 4.4 下 相关的p2p代码在frameworks/base/wifi/java/android/net/wifi/p2p/
分享到:
评论

相关推荐

    与Wi-Fi直接连接-Connecting with Wi-Fi Direct

    Wi-Fi Direct是一种无线通信技术,它允许设备在不需要传统无线网络或热点的情况下,直接连接到彼此。这种技术的优势在于它提供了更广泛的通讯范围,相较于蓝牙技术,Wi-Fi Direct能够在更大的距离上进行稳定的数据...

    Android源码——Android之Wifi学习教程.zip

    Wi-Fi的状态管理主要由`WifiStateMachine`类负责,这是一个复杂的长生命周期状态机,它定义了各种Wi-Fi状态(如Disconnected、Connecting、Connected等)并处理状态间的转换。`WifiStateMachine`与底层的硬件驱动...

    WifiStateMachine、WifiController状态图文件

    “Connecting”状态则表示正在尝试连接到某个Wi-Fi网络;“Connected”状态意味着设备已经成功连接到一个网络,并可以正常通信。 `WifiStateMachine`的工作流程通常包括以下步骤: 1. 初始化:启动时,状态机进入...

    ESP8266连接示例代码

    ESP8266是一款经济高效的Wi-Fi模块,广泛应用于物联网(IoT)设备,使得低成本的硬件能够接入无线网络。本示例代码旨在帮助开发者理解如何通过编程将ESP8266连接到Wi-Fi网络,实现设备的网络功能。下面我们将深入探讨...

    Connecting-Vehicles-Today-and-in-the-5G-Era-with-C-V2X.pdf

    The industry standard for vehicle communication, Cellular Vehicle-to-Everything (C-V2X) technology is commercially available globally today. Standardised by 3GPP, this 4G and 5G-based technology is ...

    VirtualAccessPoint 2.2

    Virtual Access Point (Virtual AP) – Share your Internet through Wi-Fi. Virtual AP is an easy-to-use software that turns any LAN-connected PC or laptop into a Wi-Fi wireless access point. So anyone ...

    Connecting-the-CE-5.0-emulator-to-VS2005.rar_How to Connect

    标题中的“Connecting-the-CE-5.0-emulator-to-VS2005”指的是将Windows CE 5.0的模拟器与Visual Studio 2005进行连接的教程。这个过程对于开发者来说至关重要,因为它允许他们在Visual Studio的集成开发环境中(IDE...

    Arduino.Android.Blueprints

    Next, you will learn how to use the Arduino Yun board to connect a standard USB camera to a local Wi-Fi network. At the end of the book, you will build a simple mobile robot, connect it to an Arduino...

    connecting-matlab-ros-for-autonomous-driving

    ### MATLAB与ROS在自动驾驶领域的融合 #### 一、引言 随着自动驾驶技术的快速发展,越来越多的技术工具被应用于这一领域。其中,MATLAB 和 ROS (Robot Operating System) 是两个备受关注的平台。...

    Informix-Tutorials-6 Connecting-to-Informix.pdf

    Informix 教程 6:如何将用户和工具从 Windows、Unix 和 Web 连接到 Informix Server?我们将讨论使用 Microsoft ODBC、Informix SDK、Java、PHP、DRDA 和其他选项的连接

    VC-connecting-to-MYSQL.zip_mysql vc_visual c

    在"VC connecting to MYSQL.doc"文档中,可能包含了更多关于如何在VC++中配置MySQL Connector/C++,如何处理连接错误,以及如何使用C API进行更复杂数据库操作的详细步骤和示例代码。确保仔细阅读并理解这些内容,...

    Recommendation-system-Connecting-business-users-with-innovative-solutions

    在这个"Recommendation-system-Connecting-business-users-with-innovative-solutions"项目中,我们很可能看到一个使用Python实现的推荐系统。 Python是推荐系统开发的常用语言,因为它拥有丰富的库和工具,如NumPy...

    ESP8266连接WiFi获取网络时间的完整代码

    ESP8266是一款经济实惠且功能强大的Wi-Fi模块,广泛应用于IoT(物联网)项目中,如智能家居、远程控制等。它能够使微控制器连接到Wi-Fi网络,实现数据传输和网络交互。在本教程中,我们将关注ESP8266如何连接WiFi并...

    Arduino esp8266 wifi库 2.4.2版本

    ESP8266是一款低成本、高性能的Wi-Fi SOC(系统级芯片),它集成了Wi-Fi收发器、微控制器和内存,使得开发人员能够轻松地将物联网功能添加到他们的项目中。此库的2.4.2版本是经过多次迭代优化后的稳定版本,提供了...

    connecting-the-dots-sample:文章“连接点”的示例应用

    本文将围绕“连接点”这一概念,结合提供的“connecting-the-dots-sample”示例应用,深入探讨Kotlin在实际项目中的应用。 “连接点”可能是指在软件开发中将各个功能模块或数据流串联起来的方式,这在很多场景下是...

    Professional Android 4 Application Development 源代码

    Transferring Data Using Wi-Fi Direct Near Field Communication Chapter 17: Telephony and SMS Hardware Support for Telephony Using Telephony Introducing SMS and MMS Introducing SIP and VOIP Chapter 18: ...

    ANSYS仿真案例Workbench有限元计算实例结果源文件流体fluent模型_connecting-rod-277.zip

    《ANSYS Workbench结合Fluent进行流体仿真分析——连杆模型详解》 ANSYS Workbench是一款集成化、多物理场的仿真平台,它提供了包括结构、热、流体、电磁等多个领域的仿真工具。在本案例中,我们将重点讨论如何使用...

    ESP32基于VScode_PlatformIO_发送邮件源码

    ESP32是一款强大的微控制器,广泛应用于物联网(IoT)项目,因为它集成了Wi-Fi和蓝牙功能。在本项目中,我们将探讨如何使用VSCode(Visual Studio Code)结合PlatformIO扩展来开发一个ESP32程序,该程序能够发送电子...

    WiFi-CC3200:用于 energia cc3200 的 WiFi 库

    1. **网络连接**:该库提供了API,用于建立和维护Wi-Fi连接,包括连接到Wi-Fi接入点(AP)和配置网络参数,如SSID(服务集标识符)和密码。 2. **安全模式**:库支持多种安全协议,如WEP、WPA、WPA2等,确保无线...

Global site tag (gtag.js) - Google Analytics