【Android Developers Training】 77. 使用Wi-F

系统 1888 0

注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好。

原文链接: http://developer.android.com/training/connect-devices-wirelessly/nsd-wifi-direct.html


在这系列课程的第一节课中(博客链接: http://www.cnblogs.com/jdneo/p/3579936.html ),向你展示了如何发现连接到本地网络上的服务。然而,使用Wi-Fi Peer-to-Peer(P2P)服务搜索会允许你直接发现附近设备的服务,而不需要连接到网络中。你也可以对外广播目前正在你的设备上运行的服务。这些功能帮助你和其它应用进行通信,甚至是当无法获取本地网络或者热点的情况下。

虽然此API所要达到的目的,和之前课程中所说的NSD API非常类似,但是实现它们的代码却是不同的。这节课将向你展示如何使用Wi-Fi P2P从其他设备发现可获得的服务。这节课假设你已经对 Wi-Fi P2P 的API有了一定的了解。


一). 配置清单文件

为了使用Wi-Fi P2P,需要在你的清单文件中添加 CHANGE_WIFI_STATE ACCESS_WIFI_STATE INTERNET 权限。虽然Wi-Fi P2P不需要网络连接,但是它使用的是标准的Java套接字,而在Android中使用它们则需要声明对应的权限许可:

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

    ...
      
    

二). 添加一个本地服务

如果你正在提供一个本地服务,你需要为服务搜索注册它。一旦你的本地服务注册了,框架将会自动响应Peer所发起的服务搜索请求。

要创建一个本地服务:

  1. 创建一个 WifiP2pServiceInfo 对象;
  2. 用你的服务的信息来填充它;
  3. 调用 addLocalService() 来为服务搜索注册本地服务
      
        private
      
      
        void
      
      
         startRegistration() {

        
      
      
        //
      
      
          Create a string map containing information about your service.
      
      

        Map record = 
      
        new
      
      
         HashMap();

        record.put(
      
      "listenport"
      
        , String.valueOf(SERVER_PORT));

        record.put(
      
      "buddyname", "John Doe" + (
      
        int
      
      ) (Math.random() * 1000
      
        ));

        record.put(
      
      "available", "visible"
      
        );



        
      
      
        //
      
      
         Service information.  Pass it an instance name, service type

        
      
      
        //
      
      
         _protocol._transportlayer , and the map containing

        
      
      
        //
      
      
         information other devices will want once they connect to this one.
      
      

        WifiP2pDnsSdServiceInfo serviceInfo =
      
        

                WifiP2pDnsSdServiceInfo.newInstance(
      
      "_test", "_presence._tcp"
      
        , record);



        
      
      
        //
      
      
         Add the local service, sending the service info, network channel,

        
      
      
        //
      
      
         and listener that will be used to indicate success or failure of

        
      
      
        //
      
      
         the request.
      
      

        mManager.addLocalService(channel, serviceInfo, 
      
        new
      
      
         ActionListener() {

            @Override

            
      
      
        public
      
      
        void
      
      
         onSuccess() {

                
      
      
        //
      
      
         Command successful! Code isn't necessarily needed here,

                
      
      
        //
      
      
         Unless you want to update the UI or add logging statements.
      
      
                    }



            @Override

            
      
      
        public
      
      
        void
      
       onFailure(
      
        int
      
      
         arg0) {

                
      
      
        //
      
      
         Command failed.  Check for P2P_UNSUPPORTED, ERROR, or BUSY
      
      
                    }

        });

    }
      
    

二). 发现附近的服务

Android会使用回调函数来通知你的应用可以获取的服务,所以要做的第一件事情就是配置它们。创建一个 WifiP2pManager.DnsSdTxtRecordListener 来监听进入的记录。这个记录作为一个可选项被广播至其它设备。当有一个记录进来了,可以将设备地址以及其它 你想要的其它信息拷贝到一个当前方法之外的一个数据结构中,这样你可以在之后的某一个阶段去访问它。下面的例子假设收到的记录包含有一个“ buddyname ”字段,用以用户身份识别。

      
        final
      
       HashMap<String, String> buddies = 
      
        new
      
       HashMap<String, String>
      
        ();

...


      
      
        private
      
      
        void
      
      
         discoverService() {

    DnsSdTxtRecordListener txtListener 
      
      = 
      
        new
      
      
         DnsSdTxtRecordListener() {

        @Override

        
      
      
        /*
      
      
         Callback includes:

         * fullDomain: full domain name: e.g "printer._ipp._tcp.local."

         * record: TXT record dta as a map of key/value pairs.

         * device: The device running the advertised service.

         
      
      
        */
      
      
        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记录和对应的服务信息连接到一起。一旦这两个监听器都实现了,使用 setDnsSdResponseListeners() 方法将它们添加到 WifiP2pManager 中。

      
        private
      
      
        void
      
      
         discoverService() {

...



    DnsSdServiceResponseListener servListener 
      
      = 
      
        new
      
      
         DnsSdServiceResponseListener() {

        @Override

        
      
      
        public
      
      
        void
      
      
         onDnsSdServiceAvailable(String instanceName, String registrationType,

                WifiP2pDevice resourceType) {



                
      
      
        //
      
      
         Update the device name with the human-friendly version from

                
      
      
        //
      
      
         the DnsTxtRecord, assuming one arrived.
      
      

                resourceType.deviceName =
      
         buddies

                        .containsKey(resourceType.deviceAddress) 
      
      ?
      
         buddies

                        .get(resourceType.deviceAddress) : resourceType.deviceName;



                
      
      
        //
      
      
         Add to the custom adapter defined specifically for showing

                
      
      
        //
      
      
         wifi devices.
      
      

                WiFiDirectServicesList fragment =
      
         (WiFiDirectServicesList) getFragmentManager()

                        .findFragmentById(R.id.frag_peerlist);

                WiFiDevicesAdapter adapter 
      
      =
      
         ((WiFiDevicesAdapter) fragment

                        .getListAdapter());



                adapter.add(resourceType);

                adapter.notifyDataSetChanged();

                Log.d(TAG, 
      
      "onBonjourServiceAvailable " +
      
         instanceName);

        }

    };



    mManager.setDnsSdResponseListeners(channel, servListener, txtListener);

    ...

}
      
    

现在创建一个服务请求并且调用 addServiceRequest() 。该方法必须接受一个监听器参数来报告结果是成功的还是失败的。

              serviceRequest =
      
         WifiP2pDnsSdServiceRequest.newInstance();

        mManager.addServiceRequest(channel,

                serviceRequest,

                
      
      
        new
      
      
         ActionListener() {

                    @Override

                    
      
      
        public
      
      
        void
      
      
         onSuccess() {

                        
      
      
        //
      
      
         Success!
      
      
                            }



                    @Override

                    
      
      
        public
      
      
        void
      
       onFailure(
      
        int
      
      
         code) {

                        
      
      
        //
      
      
         Command failed.  Check for P2P_UNSUPPORTED, ERROR, or BUSY
      
      
                            }

                });
      
    

最后,调用 discoverServices()

              mManager.discoverServices(channel, 
      
        new
      
      
         ActionListener() {



            @Override

            
      
      
        public
      
      
        void
      
      
         onSuccess() {

                
      
      
        //
      
      
         Success!
      
      
                    }



            @Override

            
      
      
        public
      
      
        void
      
       onFailure(
      
        int
      
      
         code) {

                
      
      
        //
      
      
         Command failed.  Check for P2P_UNSUPPORTED, ERROR, or BUSY
      
      
        if
      
       (code ==
      
         WifiP2pManager.P2P_UNSUPPORTED) {

                    Log.d(TAG, 
      
      "P2P isn't supported on this device."
      
        );

                
      
      
        else
      
      
        if
      
      
        (...)

                    ...

            }

        });
      
    

如果所有代码都运行正常,太好了,你已经做到了!如果你遇到了问题,记住你执行的异步调用会接受一个 WifiP2pManager.ActionListener 作为参数,然后它会提供给你回调函数来指明成果或失败。若要诊断问题所在,在 onFailure() 中添加调试代码。该方法提供的错误代码会提示问题产生的原因。下面是一些可能的错误值及它们的含义:

P2P_UNSUPPORTED

在运行程序的设备上不支持Wi-Fi P2P。

BUSY

系统太忙以致无法处理请求。

ERROR

由于一个内部错误导致操作失败。

【Android Developers Training】 77. 使用Wi-Fi P2P进行服务搜索


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论