日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

【Android Developers Training】 75. 使用NSD

系統(tǒng) 2076 0

注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術(shù)一般,由于喜愛(ài)安卓而產(chǎn)生了翻譯的念頭,純屬個(gè)人興趣愛(ài)好。

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


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

這節(jié)課將展示如何構(gòu)建一個(gè)應(yīng)用,它可以將其名字和 連接 信息廣播至所在的本地網(wǎng)絡(luò),并搜索其它正在做同樣事情的應(yīng)用。最終,這節(jié)課將展示如何連接運(yùn)行在另一設(shè)備上的應(yīng)用。


一). 在網(wǎng)絡(luò)上注冊(cè)你的服務(wù)

Note:

這一步是可選的,如果你對(duì)于將你的應(yīng)用服務(wù)廣播至本地網(wǎng)絡(luò)并不關(guān)心,你可以跳至下一節(jié)。

為了在本地網(wǎng)絡(luò)注冊(cè)你的服務(wù),首先創(chuàng)建一個(gè) NsdServiceInfo 對(duì)象。這個(gè)對(duì)象提供了網(wǎng)絡(luò)上其它設(shè)備在決定是否要鏈接到你提供的服務(wù)時(shí),所要使用到的信息。

      
        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);

    ....

}
      
    

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

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

Note:

國(guó)際號(hào)碼分配機(jī)構(gòu)(IANA)管理了一個(gè)集中、權(quán)威的服務(wù)類型列表,這一列表被服務(wù)搜索協(xié)議,如NSD和Bonjour。你可以 下載 這個(gè)列表。如果你希望使用一個(gè)新的服務(wù)類型,你需要填寫 IANA端口和服務(wù)注冊(cè)申請(qǐng)表 中維護(hù)它。

當(dāng)配置了你的服務(wù)的端口,避免對(duì)它進(jìn)行硬編碼因?yàn)檫@可能會(huì)和其它應(yīng)用產(chǎn)生沖突。例如,假設(shè)你的應(yīng)用一直使用1337端口,那么將會(huì)有潛在的可能性與其它使用相同端口的已安裝應(yīng)用產(chǎn)生沖突。解決方案是使用設(shè)備的下一個(gè)可使用端口。因?yàn)檫@一信息會(huì)通過(guò)一個(gè)服務(wù)廣播提供給其它應(yīng)用,在編譯期間,你的應(yīng)用所使用的端口無(wú)需被其它應(yīng)用知道。應(yīng)用可以可以通過(guò)服務(wù)廣播在連接到你的服務(wù)之前來(lái)得到這一信息。

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

      
        public
      
      
        void
      
      
         initializeServerSocket() {

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

    mServerSocket = 
      
        new
      
       ServerSocket(0
      
        );



    
      
      
        //
      
      
         Store the chosen port.
      
      

    mLocalPort =
      
          mServerSocket.getLocalPort();

    ...

}
      
    

現(xiàn)在你已經(jīng)定義了 NsdServiceInfo 對(duì)象,你需要實(shí)現(xiàn) RegistrationListener 接口。這個(gè)接口包括了Android系統(tǒng)所使用的回調(diào)函數(shù),以此告知你的應(yīng)用服務(wù)的注冊(cè)和注銷是否成功。

      
        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.
      
      
                }

    };

}
      
    

現(xiàn)在你具有了注冊(cè)服務(wù)所需要的代碼了。調(diào)用方法: registerService()

注意到這個(gè)方法是異步的,所以任何需要運(yùn)行的代碼,必須在服務(wù)注冊(cè)后運(yùn)行。這些代碼寫在 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);

}
      
    

二). 在網(wǎng)絡(luò)上發(fā)現(xiàn)服務(wù)

網(wǎng)絡(luò)讓生活變得豐富,從網(wǎng)絡(luò)打印機(jī)到網(wǎng)絡(luò)相機(jī)。讓你的應(yīng)用能夠看見(jiàn)這一充滿活力的生態(tài)系統(tǒng)的關(guān)鍵是服務(wù)搜索。你的應(yīng)用需要再網(wǎng)絡(luò)上監(jiān)聽服務(wù)來(lái)查詢當(dāng)前能夠獲得哪些服務(wù),并且排除任何應(yīng)用無(wú)法實(shí)現(xiàn)的服務(wù)。

服務(wù)搜索,和服務(wù)注冊(cè)類似,有兩步要做:為相關(guān)的回調(diào)函數(shù)配置一個(gè)搜索監(jiān)聽器,為 discoverServices() 執(zhí)行一次異步調(diào)用。

首先,實(shí)例化一個(gè)匿名類,它實(shí)現(xiàn)了 NsdManager.DiscoveryListener 。下面的代碼片段為一個(gè)例子:

      
        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使用這個(gè)接口的方法來(lái)通知你的應(yīng)用何時(shí)開始搜索,何時(shí)失敗,或者何時(shí)服務(wù)發(fā)現(xiàn)或丟失了(丟失即無(wú)法獲取服務(wù))。注意上述代碼樣例在一個(gè)服務(wù)搜索到了以后執(zhí)行了一些檢查。

  1. 找到的服務(wù)的服務(wù)名字,會(huì)和本地服務(wù)的服務(wù)名字進(jìn)行匹配,來(lái)確定設(shè)備是否接受到了它自己發(fā)出去的廣播。
  2. 檢查服務(wù)類型,來(lái)檢查你的應(yīng)用是否能夠連接此類型的服務(wù)。
  3. 檢查服務(wù)名字來(lái)確認(rèn)是否連接到了正確的應(yīng)用。

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

在設(shè)置了監(jiān)聽器之后,調(diào)用 discoverServices() ,將你的應(yīng)用要查找的服務(wù)類型,使用的搜索協(xié)議,和你剛創(chuàng)建過(guò)的監(jiān)聽器作為參數(shù)傳入。

      
        mNsdManager.discoverServices(

        SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
      
    

三). 連接網(wǎng)絡(luò)上的服務(wù)

當(dāng)你的應(yīng)用發(fā)現(xiàn)了一個(gè)網(wǎng)絡(luò)上要連接的服務(wù),它必須首先使用 resolveService() 方法來(lái)確定該服務(wù)的連接信息。實(shí)現(xiàn)一個(gè) NsdManager.ResolveListener ,并傳遞給該方法,并用它來(lái)獲得一個(gè)包含連接信息的 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();

        }

    };

}
      
    

一旦服務(wù)解析完成了,你的應(yīng)用會(huì)收到詳細(xì)的服務(wù)信息,包括一個(gè)IP地址和一個(gè)端口號(hào)。這些就是用來(lái)和服務(wù)創(chuàng)建連接所需要的所有東西。


四). 應(yīng)用關(guān)閉時(shí)注銷你的服務(wù)

在應(yīng)用的生命周期恰當(dāng)?shù)貑⒂没蚪肗SD功能是很重要的。在應(yīng)用關(guān)閉時(shí)注銷服務(wù)可以阻止其它應(yīng)用誤認(rèn)為你的服務(wù)仍然是啟用狀態(tài)并嘗試連接。同時(shí),服務(wù)搜索是一個(gè)很消耗資源的操作,應(yīng)該在父Activity被暫停時(shí)停止搜索,而在父Activity恢復(fù)時(shí)重新啟用。覆寫你的Activity生命周期函數(shù),并插入代碼來(lái)啟動(dòng)或停止服務(wù)廣播,并在恰當(dāng)?shù)貢r(shí)機(jī)執(zhí)行搜索。

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


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

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

【本文對(duì)您有幫助就好】

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

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 出国| 洪雅县| 贵南县| 铁岭市| 象州县| 邛崃市| 岑巩县| 富顺县| 德州市| 伊金霍洛旗| 佛教| 泸州市| 武强县| 玛曲县| 义马市| 滦平县| 那坡县| 灯塔市| 麻城市| 元江| 凤阳县| 左贡县| 敖汉旗| 宁国市| 石棉县| 错那县| 石柱| 交口县| 芮城县| 东乡| 长顺县| 满城县| 汽车| 民丰县| 北京市| 渭源县| 新兴县| 余干县| 隆尧县| 衡山县| 郑州市|