亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

【Android Developers Training】 75. 使用NSD

系統 1905 0

注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術一般,由于喜愛安卓而產生了翻譯的念頭,純屬個人興趣愛好。

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


將網絡服務搜索(NSD)添加至你的應用允許你的用戶識別在本地網絡的其它設備,這些設備提供了你的應用所需要的服務。這一特性對很多P2P類應用非常有用,如:文件共享,多人游戲等。Android的NSD API簡化了你實現該功能特性所需要做的事情。

這節課將展示如何構建一個應用,它可以將其名字和 連接 信息廣播至所在的本地網絡,并搜索其它正在做同樣事情的應用。最終,這節課將展示如何連接運行在另一設備上的應用。


一). 在網絡上注冊你的服務

Note:

這一步是可選的,如果你對于將你的應用服務廣播至本地網絡并不關心,你可以跳至下一節。

為了在本地網絡注冊你的服務,首先創建一個 NsdServiceInfo 對象。這個對象提供了網絡上其它設備在決定是否要鏈接到你提供的服務時,所要使用到的信息。

      
        public
      
      
        void
      
       registerService(
      
        int
      
      
         port) {

    
      
      
        //
      
      
         Create the NsdServiceInfo object, and populate it.
      
      

    NsdServiceInfo serviceInfo  = 
      
        new
      
      
         NsdServiceInfo();



    
      
      
        //
      
      
         The name is subject to change based on conflicts

    
      
      
        //
      
      
         with other services advertised on the same network.
      
      

    serviceInfo.setServiceName("NsdChat"
      
        );

    serviceInfo.setServiceType(
      
      "_http._tcp"
      
        );

    serviceInfo.setPort(port);

    ....

}
      
    

這段代碼將服務名設置為“NsdChat”。這個名字對于任何在網絡上,并正在使用NSD尋找本地服務的設備都是可見的。記住這個名字必須是在網絡上是唯一的,不過Android會自動解決名字沖突的問題。如果兩個網絡上的設備都安裝了NsdChat應用,他們中的一個會自動改變服務名稱,如:“ NsdChat(1) ”。

第二個變量設置了服務類型,指定了傳輸層和應用層所使用的協議。語法的格式是:“_<應用層協議>._<傳輸層協議>”,在代碼片段中,應用使用了運行于TCP之上的HTTP。如果一個應用提供了打印服務(例如,一個網絡打印機)那么會將服務類型設置為“_ipp.tcp”。

Note:

國際號碼分配機構(IANA)管理了一個集中、權威的服務類型列表,這一列表被服務搜索協議,如NSD和Bonjour。你可以 下載 這個列表。如果你希望使用一個新的服務類型,你需要填寫 IANA端口和服務注冊申請表 中維護它。

當配置了你的服務的端口,避免對它進行硬編碼因為這可能會和其它應用產生沖突。例如,假設你的應用一直使用1337端口,那么將會有潛在的可能性與其它使用相同端口的已安裝應用產生沖突。解決方案是使用設備的下一個可使用端口。因為這一信息會通過一個服務廣播提供給其它應用,在編譯期間,你的應用所使用的端口無需被其它應用知道。應用可以可以通過服務廣播在連接到你的服務之前來得到這一信息。

如果你使用套接字鏈接,下面展示了你應該如何初始化一個套接字鏈接到任一可以獲得的端口,方法是簡單地設置它為0。

      
        public
      
      
        void
      
      
         initializeServerSocket() {

    
      
      
        //
      
      
         Initialize a server socket on the next available port.
      
      

    mServerSocket = 
      
        new
      
       ServerSocket(0
      
        );



    
      
      
        //
      
      
         Store the chosen port.
      
      

    mLocalPort =
      
          mServerSocket.getLocalPort();

    ...

}
      
    

現在你已經定義了 NsdServiceInfo 對象,你需要實現 RegistrationListener 接口。這個接口包括了Android系統所使用的回調函數,以此告知你的應用服務的注冊和注銷是否成功。

      
        public
      
      
        void
      
      
         initializeRegistrationListener() {

    mRegistrationListener 
      
      = 
      
        new
      
      
         NsdManager.RegistrationListener() {



        @Override

        
      
      
        public
      
      
        void
      
      
         onServiceRegistered(NsdServiceInfo NsdServiceInfo) {

            
      
      
        //
      
      
         Save the service name.  Android may have changed it in order to

            
      
      
        //
      
      
         resolve a conflict, so update the name you initially requested

            
      
      
        //
      
      
         with the name Android actually used.
      
      

            mServiceName =
      
         NsdServiceInfo.getServiceName();

        }



        @Override

        
      
      
        public
      
      
        void
      
       onRegistrationFailed(NsdServiceInfo serviceInfo, 
      
        int
      
      
         errorCode) {

            
      
      
        //
      
      
         Registration failed!  Put debugging code here to determine why.
      
      
                }



        @Override

        
      
      
        public
      
      
        void
      
      
         onServiceUnregistered(NsdServiceInfo arg0) {

            
      
      
        //
      
      
         Service has been unregistered.  This only happens when you call

            
      
      
        //
      
      
         NsdManager.unregisterService() and pass in this listener.
      
      
                }



        @Override

        
      
      
        public
      
      
        void
      
       onUnregistrationFailed(NsdServiceInfo serviceInfo, 
      
        int
      
      
         errorCode) {

            
      
      
        //
      
      
         Unregistration failed.  Put debugging code here to determine why.
      
      
                }

    };

}
      
    

現在你具有了注冊服務所需要的代碼了。調用方法: registerService()

注意到這個方法是異步的,所以任何需要運行的代碼,必須在服務注冊后運行。這些代碼寫在 onServiceRegistered() 方法中。

      
        public
      
      
        void
      
       registerService(
      
        int
      
      
         port) {

    NsdServiceInfo serviceInfo  
      
      = 
      
        new
      
      
         NsdServiceInfo();

    serviceInfo.setServiceName(
      
      "NsdChat"
      
        );

    serviceInfo.setServiceType(
      
      "_http._tcp."
      
        );

    serviceInfo.setPort(port);



    mNsdManager 
      
      =
      
         Context.getSystemService(Context.NSD_SERVICE);



    mNsdManager.registerService(

            serviceInfo, NsdManager.PROTOCOL_DNS_SD, mRegistrationListener);

}
      
    

二). 在網絡上發現服務

網絡讓生活變得豐富,從網絡打印機到網絡相機。讓你的應用能夠看見這一充滿活力的生態系統的關鍵是服務搜索。你的應用需要再網絡上監聽服務來查詢當前能夠獲得哪些服務,并且排除任何應用無法實現的服務。

服務搜索,和服務注冊類似,有兩步要做:為相關的回調函數配置一個搜索監聽器,為 discoverServices() 執行一次異步調用。

首先,實例化一個匿名類,它實現了 NsdManager.DiscoveryListener 。下面的代碼片段為一個例子:

      
        public
      
      
        void
      
      
         initializeDiscoveryListener() {



    
      
      
        //
      
      
         Instantiate a new DiscoveryListener
      
      

    mDiscoveryListener = 
      
        new
      
      
         NsdManager.DiscoveryListener() {



        
      
      
        //
      
      
          Called as soon as service discovery begins.
      
      
                @Override

        
      
      
        public
      
      
        void
      
      
         onDiscoveryStarted(String regType) {

            Log.d(TAG, 
      
      "Service discovery started"
      
        );

        }



        @Override

        
      
      
        public
      
      
        void
      
      
         onServiceFound(NsdServiceInfo service) {

            
      
      
        //
      
      
         A service was found!  Do something with it.
      
      

            Log.d(TAG, "Service discovery success" +
      
         service);

            
      
      
        if
      
       (!
      
        service.getServiceType().equals(SERVICE_TYPE)) {

                
      
      
        //
      
      
         Service type is the string containing the protocol and

                
      
      
        //
      
      
         transport layer for this service.
      
      

                Log.d(TAG, "Unknown Service Type: " +
      
         service.getServiceType());

            } 
      
      
        else
      
      
        if
      
      
         (service.getServiceName().equals(mServiceName)) {

                
      
      
        //
      
      
         The name of the service tells the user what they'd be

                
      
      
        //
      
      
         connecting to. It could be "Bob's Chat App".
      
      

                Log.d(TAG, "Same machine: " +
      
         mServiceName);

            } 
      
      
        else
      
      
        if
      
       (service.getServiceName().contains("NsdChat"
      
        )){

                mNsdManager.resolveService(service, mResolveListener);

            }

        }



        @Override

        
      
      
        public
      
      
        void
      
      
         onServiceLost(NsdServiceInfo service) {

            
      
      
        //
      
      
         When the network service is no longer available.

            
      
      
        //
      
      
         Internal bookkeeping code goes here.
      
      

            Log.e(TAG, "service lost" +
      
         service);

        }



        @Override

        
      
      
        public
      
      
        void
      
      
         onDiscoveryStopped(String serviceType) {

            Log.i(TAG, 
      
      "Discovery stopped: " +
      
         serviceType);

        }



        @Override

        
      
      
        public
      
      
        void
      
       onStartDiscoveryFailed(String serviceType, 
      
        int
      
      
         errorCode) {

            Log.e(TAG, 
      
      "Discovery failed: Error code:" +
      
         errorCode);

            mNsdManager.stopServiceDiscovery(
      
      
        this
      
      
        );

        }



        @Override

        
      
      
        public
      
      
        void
      
       onStopDiscoveryFailed(String serviceType, 
      
        int
      
      
         errorCode) {

            Log.e(TAG, 
      
      "Discovery failed: Error code:" +
      
         errorCode);

            mNsdManager.stopServiceDiscovery(
      
      
        this
      
      
        );

        }

    };

}
      
    

NSD的API使用這個接口的方法來通知你的應用何時開始搜索,何時失敗,或者何時服務發現或丟失了(丟失即無法獲取服務)。注意上述代碼樣例在一個服務搜索到了以后執行了一些檢查。

  1. 找到的服務的服務名字,會和本地服務的服務名字進行匹配,來確定設備是否接受到了它自己發出去的廣播。
  2. 檢查服務類型,來檢查你的應用是否能夠連接此類型的服務。
  3. 檢查服務名字來確認是否連接到了正確的應用。

檢查服務名字并不總是必須的,如果你希望連接到某一個確切的應用的話才會需要。例如,這個應用可能可能只希望連接到在其他設備上運行的其自身的實例。然而,如果應用希望連接到一個網絡打印機,那么吧服務類型設置為“ _ipp._tcp ”就夠了。

在設置了監聽器之后,調用 discoverServices() ,將你的應用要查找的服務類型,使用的搜索協議,和你剛創建過的監聽器作為參數傳入。

      
        mNsdManager.discoverServices(

        SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
      
    

三). 連接網絡上的服務

當你的應用發現了一個網絡上要連接的服務,它必須首先使用 resolveService() 方法來確定該服務的連接信息。實現一個 NsdManager.ResolveListener ,并傳遞給該方法,并用它來獲得一個包含連接信息的 NsdServiceInfo

      
        public
      
      
        void
      
      
         initializeResolveListener() {

    mResolveListener 
      
      = 
      
        new
      
      
         NsdManager.ResolveListener() {



        @Override

        
      
      
        public
      
      
        void
      
       onResolveFailed(NsdServiceInfo serviceInfo, 
      
        int
      
      
         errorCode) {

            
      
      
        //
      
      
         Called when the resolve fails.  Use the error code to debug.
      
      

            Log.e(TAG, "Resolve failed" +
      
         errorCode);

        }



        @Override

        
      
      
        public
      
      
        void
      
      
         onServiceResolved(NsdServiceInfo serviceInfo) {

            Log.e(TAG, 
      
      "Resolve Succeeded. " +
      
         serviceInfo);



            
      
      
        if
      
      
         (serviceInfo.getServiceName().equals(mServiceName)) {

                Log.d(TAG, 
      
      "Same IP."
      
        );

                
      
      
        return
      
      
        ;

            }

            mService 
      
      =
      
         serviceInfo;

            
      
      
        int
      
       port =
      
         mService.getPort();

            InetAddress host 
      
      =
      
         mService.getHost();

        }

    };

}
      
    

一旦服務解析完成了,你的應用會收到詳細的服務信息,包括一個IP地址和一個端口號。這些就是用來和服務創建連接所需要的所有東西。


四). 應用關閉時注銷你的服務

在應用的生命周期恰當地啟用或禁用NSD功能是很重要的。在應用關閉時注銷服務可以阻止其它應用誤認為你的服務仍然是啟用狀態并嘗試連接。同時,服務搜索是一個很消耗資源的操作,應該在父Activity被暫停時停止搜索,而在父Activity恢復時重新啟用。覆寫你的Activity生命周期函數,并插入代碼來啟動或停止服務廣播,并在恰當地時機執行搜索。

      
        //
      
      
        In your application's Activity
      
      
        

    @Override

    
      
      
        protected
      
      
        void
      
      
         onPause() {

        
      
      
        if
      
       (mNsdHelper != 
      
        null
      
      
        ) {

            mNsdHelper.tearDown();

        }

        
      
      
        super
      
      
        .onPause();

    }



    @Override

    
      
      
        protected
      
      
        void
      
      
         onResume() {

        
      
      
        super
      
      
        .onResume();

        
      
      
        if
      
       (mNsdHelper != 
      
        null
      
      
        ) {

            mNsdHelper.registerService(mConnection.getLocalPort());

            mNsdHelper.discoverServices();

        }

    }



    @Override

    
      
      
        protected
      
      
        void
      
      
         onDestroy() {

        mNsdHelper.tearDown();

        mConnection.tearDown();

        
      
      
        super
      
      
        .onDestroy();

    }



    
      
      
        //
      
      
         NsdHelper's tearDown method
      
      
        public
      
      
        void
      
      
         tearDown() {

        mNsdManager.unregisterService(mRegistrationListener);

        mNsdManager.stopServiceDiscovery(mDiscoveryListener);

    }
      
    

【Android Developers Training】 75. 使用NSD


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 午夜视频网址 | 日韩中文字幕在线观看视频 | 欧美香蕉爽爽人人爽观看猫咪 | 99爱视频免费高清在线观看 | 欧美精品aaa久久久影院 | 免费一级a毛片在线播放视 免费一级成人毛片 | 久久久全国免费视频 | 亚洲图片色图 | 国产区在线观看 | 久久婷婷五色综合夜啪 | www久| 玖玖国产精品视频 | 国产网友自拍视频 | www四虎| 久久久综合久久 | 欧美成人xxxx | 亚洲欧美片 | 在线不卡免费视频 | 久久久久久夜精品精品免费 | 欧美不卡视频 | 成人国产精品视频 | 热99这里只有精品 | 国产一区在线观看视频 | 中文视频在线 | 欧美一区二区在线免费观看 | 激情影院免费 | 成人免费毛片网站 | 日本久色| 中国一级特黄高清免费的大片 | 国产成人精品免费视频网页大全 | 美女被爆羞羞视频网站视频 | 欧美特黄a级猛片a级 | 97精品国产高清久久久久蜜芽 | 欧美日韩久久中文字幕 | 欧美日韩亚 | 99热这里只有精品69 | 天码毛片一区二区三区入口 | 久久久99精品免费观看 | 久久久久综合网久久 | 综合色天天| 久草美女|