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

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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值