android学习(十九) 使用无线连接设备(二) 用Wi-Fi P2P创建连接

来源:互联网 发布:网络主播当红10首歌曲 编辑:程序博客网 时间:2024/06/08 12:03

WIFI-P2P允许你的应用快速查找和交互附近的设备,这是一个在蓝牙范围外的功能。
WIFI-P2P API允许应用在无需连接网络或热点的情况下连接附近设备。如果你的应用被设计成一个安全的近距离的网络,WIFI是一个更合适的选择。

设置应用的权限

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

设置广播接收器和P2P管理

为了使用WIFI-P2P,你需要监听广播Intent,告诉你的应用某些事情已经发生。实例化IntentFilter并且设置如下监听:
WIFI_P2P_STATE_CHANGED_ACTION:表示WIFI-P2P是否启动。
WIFI_P2P_PEERS_CHANGED_ACTION:表示可用的端口列表已经改变。
WIFI_P2P_CONNECTION_CHANGED_ACTION:表示Wi-Fi P2P连接状态已发生变化。
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION:表示此设备的配置详细信息已更改。

    private final IntentFilter intentFilter = new IntentFilter();    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);        intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);        intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);        intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);    }

获取WifiP2pManager并且调用initialize()方法,返回一个WifiP2pManager.Channel类。

    ...    private WifiP2pManager.Channel mChannel;    private WifiP2pManager mManager;    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ...        mManager = (WifiP2pManager) this.getSystemService(Context.WIFI_P2P_SERVICE);        mChannel = mManager.initialize(this,getMainLooper(),null);    }

接下来创建一个BroadcastReceiver类,它用于监听系统的Wi-Fi P2P的状态变化,在onReceive()方法中,需要添加一些基本的判断条件来处理每种P2P的状态并处理:

public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {    private MainActivity activity;    private WifiP2pManager mManager;    private Channel mChannel;    public WiFiDirectBroadcastReceiver(WifiP2pManager mManager, Channel mChannel, MainActivity activity) {        this.activity = activity;        this.mManager = mManager;        this.mChannel = mChannel;    }    @Override    public void onReceive(Context context, Intent intent) {        String action = intent.getAction();        if(WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)){            //确认WIFI-P2P是否启动            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)){            //此设备的配置详细信息已更改            Toast.makeText(context.getApplicationContext(),action,Toast.LENGTH_SHORT).show();        }    }}

最后,将广播接收器与意图过滤器添加到上下文中,并需要在Activity暂停的时候注销这个广播接收器。放置这些代码的最佳位置就是onResume()方法与onPause()方法。

    @Override    protected void onResume() {        super.onResume();        receiver = new WiFiDirectBroadcastReceiver(mManager,mChannel,this);        registerReceiver(receiver,intentFilter);    }    @Override    protected void onPause() {        super.onPause();        unregisterReceiver(receiver);    }    public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled){        if(isWifiP2pEnabled){            Toast.makeText(this,"WifiP2p连接成功",Toast.LENGTH_SHORT).show();        } else {            Toast.makeText(this,"WifiP2p连接失败",Toast.LENGTH_SHORT).show();        }    }

初始化端口搜索

调用WifiP2pManager.discoverPeers()他继承WifiP2pManager.ActionListener接口用于监听搜索成功与否

mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {            @Override            public void onSuccess() {            }            @Override            public void onFailure(int reason) {                //提醒用户出错了            }        });

要记住,这里只是初始化了端点搜索。discoverPeers()方法启动搜索进程后会立即返回。如果端点搜索进程成功初始化,那么系统会自动调用初始化时设置的回调方法。另外,端点搜索功能会一直保持在活动状态,直到连接初始化完成或者P2P组建立连接。


获取对等设备列表

现在获取对等列表,首先需要继承* WifiP2pManager.PeerListListener*接口,它提供了WI-FI P2P所搜索到的端点信息。添加代码到BroadcastReceiver类。

private List<WifiP2pDevice> peers = new ArrayList<>();    private WifiP2pManager.PeerListListener peerListListener = new WifiP2pManager.PeerListListener() {        @Override        public void onPeersAvailable(WifiP2pDeviceList peerList) {            List<WifiP2pDevice> refreshedPeers = (List<WifiP2pDevice>) peerList.getDeviceList();            if(!refreshedPeers.equals(peers)){                peers.clear();                peers.addAll(refreshedPeers);                //可以通过一个ListView显示                //需要多个人连接才能获取他人信息            }            if(peers.size() == 0){                Log.d(WiFiDirectActivity.TAG, "No devices found");                return;            }        }    };

现在需要重新设置WIFI_P2P_PEERS_CHANGED_ACTION的验证。

public void onReceive(Context context, Intent intent) {    ...    else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {        if (mManager != null) {            mManager.requestPeers(mChannel, peerListListener);        }        Log.d(WiFiDirectActivity.TAG, "P2P peers changed");    }...}

连接一个对等设备

为了连接一个端口,需要创建一个新的WifiP2pConfig对象,并且从WifiP2pDevice拷贝数据。代表你想连接这个设备。WifiP2pManager调用connect()方法。

 WifiP2pDevice device = peers.get(position);        WifiP2pConfig config = new WifiP2pConfig();        config.deviceAddress = device.deviceAddress;        config.wps.setup = WpsInfo.PBC;        mManager.connect(mChannel, config, new ActionListener() {            @Override            public void onSuccess() {            }            @Override            public void onFailure(int reason) {                Toast.makeText(WiFiDirectActivity.this, "连接失败",                        Toast.LENGTH_SHORT).show();            }        });

如果在你的组里面每一个设备都支持wifi直连,当你连接时,你不需要明确的告诉这个组密码。为了允许不支持WIFI直连的设备加入群,你需要调用requestGroupInfo()来检索密码。

mManager.requestGroupInfo(mChannel, new WifiP2pManager.GroupInfoListener() {            @Override            public void onGroupInfoAvailable(WifiP2pGroup group) {                if(group!=null){                    String groupPassword = group.getPassphrase();                }            }        });

上述代码中的WifiP2pManager.ActionListener接口只有在初始化成功或者失败的情况下才会调用。如果要监听连接状态的变化,需要实现WifiP2pManager.ConnectionInfoListener接口,它的方法onConnectionInfoAvailable()会在连接状态发生变化的时候回调。在多台设备连接一台设备的情况下(比如多人互动的游戏或者聊天类的APP),其中一台设备会被指定为”群组的拥有者”。

else if(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)){            Log.d("connection",action);            //连接状态改变            if(mManager==null){                Log.d("connection","null");                return;            }            NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);            if(networkInfo.isConnected()){                mManager.requestConnectionInfo(mChannel, new WifiP2pManager.ConnectionInfoListener() {                    @Override                    public void onConnectionInfoAvailable(WifiP2pInfo info) {                    //获取拥有者的地址。                        String groupOwnerAddress = info.groupOwnerAddress.getHostAddress();                            Log.d("connection",groupOwnerAddress);                        if(info.groupFormed&&info.isGroupOwner){                            //做任何只属于管理者的的任务。一个常见的情况是创建一个组所有者线程和接受权限                        }else if(info.groupFormed){                            //其他设备是对等,在这种情况下需要管理者创建对等线程。                        }                    }                });            }        }

创建一个组

如果你想让设备作为一个网络运用你的应用包括传统设备,设备不支持WIFI Direct–你应该以相同的顺序步骤在连接对等部分。除非你创建一个新的WifiP2pManager.ActionListener()使用createGroup()替代connect()

mManager.createGroup(mChannel, new WifiP2pManager.ActionListener() {    @Override    public void onSuccess() {        //设备准备接受来自同等级的传入连接。    }    @Override    public void onFailure(int reason) {        Toast.makeText(WiFiDirectActivity.this, "P2P 组创建失败",                Toast.LENGTH_SHORT).show();    }});

:如果在一个网络支持Wi-Fi Direct的所有设备,你可以使用connect()方法在每个设备因为方法然后创建组和拥有者自动选择一组。

你创建一个组后,你可以调用requestgroupinfo()检索网络上的节点的详细信息,包括设备名称和连接状态。


摘自android developer

0 0
原创粉丝点击