android学习(十九) 使用无线连接设备(三) 通过P2P搜索网络服务

使用WI-FI P2P搜索服务可以直接搜索附近的设备,而不需要专门通过本地网络。这项特性使得在没有本地网络或者热点的情况下还可以在不同的设备间进行通信。

建立清单

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

添加本地服务

如果程序提供了本地服务,还需要将该服务注册到搜索服务中。一旦本地服务完成注册,那么框架会自动的响应另一端点的搜索服务请求。

创建本地网络有以下过程:
1. 创建一个WifiP2pServiceInfo对象。
2. 将服务的相关信息填入其中。
3. 调用addLocalService()方法完成本地服务注册。

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    private void startRegistration(){
        //创建一个String表包含你服务的信息
        Map<String,String> record = new HashMap();
        record.put("listenport", String.valueOf(SERVER_PORT));
        record.put("buddyname", "John Doe" + (int) (Math.random() * 1000));
        record.put("available", "visible");

        final WifiP2pDnsSdServiceInfo serviceInfo = WifiP2pDnsSdServiceInfo.newInstance("test","_presence._tcp",record);
        mManager.addLocalService(mChannel, serviceInfo, new WifiP2pManager.ActionListener() {
            @Override
            public void onSuccess() {
            }

            @Override
            public void onFailure(int reason) {
            }
        });
    }

搜索附近设备

Android会使用回调方法来通知应用程序有可用的服务,所以首先要做的就是设置该回调。创建一个WifiP2pManager.DnsSdTxtRecordListener来监听传入的记录。这个记录由其它设备随意广播。当其中一条记录到达时,会将该设备的地址及其它相关的信息拷贝到一个外部的数据结构中,这样的话就可以晚一些访问。下面的代码假设这个记录包含一条”buddyname”的属性,用于识别用户的身份。

final HashMap<String, String> buddies = new HashMap<String, String>();
...
private void discoverService() {
    DnsSdTxtRecordListener txtListener = new DnsSdTxtRecordListener() {
        @Override
        /* 回调包括:
         * 完整域名:完整域名的名字: e.g "printer._ipp._tcp.local."
         * 记录: TXT以键值对方式记录数据
         * 设备:这个设备正在运行的公布的服务
         */
        public void onDnsSdTxtRecordAvailable(
                String fullDomain, Map record, WifiP2pDevice device) {
                Log.d(TAG, "DnsSdTxtRecord available -" + record.toString());
                buddies.put(device.deviceAddress, record.get("buddyname"));
            }
        };
    ...
}

如要获取服务的相关信息,需要创建一个WifiP2pManager.DnsSdServiceResponseListener接口。 这个接口会接收实际的连接信息。上面代码段中的Map对象将设备的地址与”buddy name”组成了键值对。服务响应监听器利用这项特性与DNS记录建立连接。一旦两个监听器都已经实现,那么将它们添加到WifiP2pManager的setDnsSdResponseListeners()方法中即可。

private void discoverService() {
...
    DnsSdServiceResponseListener servListener = new DnsSdServiceResponseListener() {
        @Override
        public void onDnsSdServiceAvailable(String instanceName, String registrationType,
                WifiP2pDevice resourceType) {
                resourceType.deviceName = buddies
                        .containsKey(resourceType.deviceAddress) ? buddies
                        .get(resourceType.deviceAddress) : resourceType.deviceName;
                //增加一个列表展示wifi设备
                WiFiDirectServicesList fragment = (WiFiDirectServicesList) getFragmentManager()
                        .findFragmentById(R.id.frag_peerlist);
                WiFiDevicesAdapter adapter = ((WiFiDevicesAdapter) fragment
                        .getListAdapter());
                adapter.add(resourceType);
                adapter.notifyDataSetChanged();
        }
    };
    mManager.setDnsSdResponseListeners(channel, servListener, txtListener);
    ...
}

接下来需要创建一个新的服务请求,然后将其作为参数调用addServiceRequest()方法,这个方法同样需要一个监听器来反应成功还是失败。

serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
        mManager.addServiceRequest(channel,
                serviceRequest,
                new ActionListener() {
                    @Override
                    public void onSuccess() {
                    }
                    @Override
                    public void onFailure(int code) {
                    }
                });

最后,调用discoverServices()方法开始搜索服务

     mManager.discoverServices(channel, new ActionListener() {
            @Override
            public void onSuccess() {
            }
            @Override
            public void onFailure(int code) {
                if (code == WifiP2pManager.P2P_UNSUPPORTED) {
                    Log.d(TAG, "当前设备不支持p2p wifi");
                }else if(...){
                    ...
            }
        });

如果回调方法失败了可能会产生以下几种错误,通过调试显示他们
P2P_UNSUPPORTED:当前设备不支持Wi-Fi P2P。
BUSY:系统处于繁忙处理状态。
ERROR:由于内部错误造成操作失败。


摘自android developer

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值