创建点对点WiFi直连——翻译自developer.android.com Training

wifi p2p api可以让设备和身边的设备相连接,而不需要网络或者热点。android的wifi p2p框架使用了wifi-direct认证的程序。wifi p2p让你的应用快速找到并连接周围的设备,与之教育,这个范围要比蓝牙更广。

这节课教你怎样使用wifi直连来找到和连接周围的设备。


建立应用的权限

要使用wifip2p,需要在manifest中添加权限CHANGE_WIFI_SATE,ACCESS_WIFI_STATE和INTERNET权限。wifip2p不需要互联网连接,但是它使用标准的javasocket,所以需要INTERNET权限。所以你需要遵循下面的权限类使用wifip2p。


        android:required="true"
        android:name="android.permission.ACCESS_WIFI_STATE"/>
    
        android:required="true"
        android:name="android.permission.CHANGE_WIFI_STATE"/>
    
        android:required="true"
        android:name="android.permission.INTERNET"/>
    ...

建立一个广播接听者和p2p管理器



要使用wifi p2p你需要监听广播intent来监听特定的事件。在你的app中设立一个intentFileter来监听下面的事情。

WIFI_P2P_STATE_CHANGED_ACTION 指示wifip2p是否可用
WIFI_P2P_PEERS_CHANGED_ACTION 指示wifip2p配对名单是否发生变化Indicates that the available peer list has changed. WIFI_P2P_CONNECTION_CHANGED_ACTION 指示wifip2p连接是否发生变化Indicates the state of Wi-Fi P2P connectivity has changed. WIFI_P2P_THIS_DEVICE_CHANGED_ACTION 指示本设备的细节配置是否发生变化Indicates this device's configuration details have changed.
private final IntentFilter intentFilter = new IntentFilter();
...
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    //  Indicates a change in the Wi-Fi P2P 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对象,一会你讲在wifip2p框架当中使用。


@Override

Channel mChannel;

public void onCreate(Bundle savedInstanceState) {
    ....
    mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
    mChannel = mManager.initialize(this, getMainLooper(), null);
}
下面创建一个BroadCastReceiver来监听系统的wifip2p的状态变化。在onReceive()方法中,添加一个来处理上面列出的每一种的P2P状态变化。



@Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
            // Determine if Wifi P2P mode is enabled or not, alert
            // the Activity.判断wifi P2p的模式有无变化,如果有的话就想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)) {

            // 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激活的时候,注册intent filter和 broadcastReceiver,当activity pause的时候注销他们。最好的是在onResume()和onPause()中进行。

    /** register the BroadcastReceiver with the intent values to be matched */
    @Override
    public void onResume() {
        super.onResume();
        receiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
        registerReceiver(receiver, intentFilter);
    }

    @Override
    public void onPause() {
        super.onPause();
        unregisterReceiver(receiver);
    }

初始化配对发现

想要发现附近的 wifiP2P设备,需要使用下面的参数调用discoverPeers方法。
- 当你初始化peer to peer Manager的时候返回的WifiP2pManager对象。
- 构建一个WifiP2pManager.ActionListener,系统将会在发现设备或者失败的时候调用其中的方法。
mManager.discoverPeers(mChannel,new WifiP2pManager.ActionListener){
@Override
public void onSuccess(){
但你发现初始化成功的时候就会调用这里。
还没有服务被实际的发现呢,所以这个方法经常被留空。配对发现在onRecive方法中,细节见下面。
}
@Overide
public void onFailure(int reasonCode){
当发现初始化失败的时候调用这里,警告用户出现了一些错误。
}

}

记住,这仅仅初始化了配对的发下。discoverPeers()方法启动了发现程序,并立即返回了。系统在发现初始化成功的时候会调用你给的 action listener中的方法来通知你成功。同样,发现会一直持续,一直到初始化成功或者p2p小组建立。


获取配对伙伴列表


现在写获取对象 和处理列表的代码。先实现WifiP2pManager.PeerListListener的接口,它可以提供发现的wifiP2p设备的 列表。下面的代码片作为例子:


private List peers=new ArrayList();

private PeerListListener peerListListener=new PeerListListener(){
@Override
public void onPeeersAvailable(WifiP2pDeviceList peerList){
//外面是旧的,里面是新的
peers.clear();
peers.addAll(peerList.getDeviceList());

//如果有AdapterView被这个数据填充了,那么这时要通知更新。例如,如果你一个可用配对的 列表。
((WiFiPeerListAdapter)getListAdapter()).notifyDataSetChanged();
if(peers.size()==0){
Log.d(WiFiDirectActivity.TAG,"No device found");
return ;
}
}
}

现在修改你的broadcast receiver在接受到action 为WIFI_p2p_PEERSpCHANGED_ACTIONS的时候在onReceiver中调用requestPeers方法。

如论如何你都要吧listener传入到receiver当中。一种方法是作为broadcastReceiver的参数传递进去。


public void onReceive(Context context, Intent intent){
……
else if(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)){
//从wifip2p管理者里面请求可用的对象。指示第一个异步调用,并且调换那个的activity会调用PeerListLisener.onPeersAvailiable()来被通知。
}
Log.d(WifiDirectActivity.TAG,"P2P peers changed);
}


现在,使用action WIFI_P2P_PEERS_CHANGED_ACTION的intent将会触发一个更新配对列表的请求。


连接到一个配对

为了连接一个配对,创建一个新的WifiP2PConfig对象,并从你要连接的WifiP2PDevice对象复制信息到前者中。接着调用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接口只能通知初始化成功和失败。想要监听其他的连接状态变化,实现WifiP2pManger.ConnnectionInfoListener接口。其中的onConnetionInfoAvailable方法将会在网络状态发生变化的时候回调。 当有多个设备要连接到一个设备的时候(比如说多个玩家的游戏,或者一个聊天app),那么这个设备应该作为群主。(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 模块。当收到这个intent的时候,调用 requestConnectionInfo()方法。这是一个异步的调用,结果将会通过作为参数传入的 listener对象中的方法来接收。
























你可能感兴趣的:(Android,API,Android)