日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android官方开发文档Training系列课程中文版:连接无线设备之网络服务搜索功能

發布時間:2024/7/5 Android 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android官方开发文档Training系列课程中文版:连接无线设备之网络服务搜索功能 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文地址:http://android.xsoftlab.net/training/connect-devices-wirelessly/index.html

引言

Android設備除了可以與服務器建立連接之外,Android無線API還允許處于同一網段下的兩臺設備建立連接,或者是物理距離相近的兩臺設備建立連接。Network Service Discovery (NSD)允許應用程序通過掃描來搜索附近可連接的設備。當然被掃描的設備也同樣需要開啟該服務。利用這項特性可以使應用程序擁有更強大的功能,比如和同伴在一個房間內玩游戲,或者從有NSD服務的網絡攝像頭上下載照片,或者遠程操控屋內的其它設備(智能家電的基礎)。

這節課將學習如何搜索其它設備并與之建立連接。需要特別說明的是,這些關鍵的API描述了如何使用NSD API來搜索可用的服務及如何利用Wi-Fi Peer-to-Peer (P2P) API來建立P2P方式的無線連接。這節課還會學習如何使用NSD與WIFI P2P結合的方式來搜索服務提供者。

使用網絡搜索服務

使用Network Service Discovery (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”。這個名稱對所有使用了USD服務的設備可見。要記住一點就是這個名稱在這個網絡環境中必須是唯一的,Android會自動處理這種名稱沖突問題。如果在同一環境下有兩個名稱為”NsdChat”的設備,那么Android會自動將其中一個命名為”NsdChat (1)”.

第二個參數設置了該服務的類型,指定了所使用的傳輸協議與運輸層。這個定義語法是”.”.在上面的代碼中,該服務使用的是運行在TCP上的HTTP協議。如果一個程序提供的是打印服務,那么它的服務類型應該是”_ipp._tcp”.

Note: 這些搜索服務協議比如NSD、Bonjour由International Assigned Numbers Authority (IANA)互聯網地址編碼分配機構統一管理。你可以通過the IANA list of service names and port numbers下載服務類型列表。如果計算使用一種新的服務類型,應當在IANA Ports and Service registration form上進行備案。

當為服務設置端口時,應避免將端口寫死,因為這個端口可能會與其他端口沖突。假設,應用程序一直在使用端口1337,則會與其它也使用了相同端口的應用程序造成端口沖突,使用設備的下一個可用端口則可以避免這種沖突。因為這個信息是由其它應用通過廣播提供的,所以在編譯時不需要知道其它應用使用的是哪個接口。相反的,應用程序會在連接到設備之前通過廣播獲得端口的信息。

如果使用Socket進行通信,下面的代碼展示了如何初始化一個Socket,并將其端口設置為萬能的端口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接口。這個接口用于通知應用程序服務的注冊于解注是成功還是失敗。

public void initializeRegistrationListener() {mRegistrationListener = new NsdManager.RegistrationListener() {@Overridepublic 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();}@Overridepublic void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {// Registration failed! Put debugging code here to determine why.}@Overridepublic void onServiceUnregistered(NsdServiceInfo arg0) {// Service has been unregistered. This only happens when you call// NsdManager.unregisterService() and pass in this listener.}@Overridepublic 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 DiscoveryListenermDiscoveryListener = new NsdManager.DiscoveryListener() {// Called as soon as service discovery begins.@Overridepublic void onDiscoveryStarted(String regType) {Log.d(TAG, "Service discovery started");}@Overridepublic 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);}}@Overridepublic void onServiceLost(NsdServiceInfo service) {// When the network service is no longer available.// Internal bookkeeping code goes here.Log.e(TAG, "service lost" + service);}@Overridepublic void onDiscoveryStopped(String serviceType) {Log.i(TAG, "Discovery stopped: " + serviceType);}@Overridepublic void onStartDiscoveryFailed(String serviceType, int errorCode) {Log.e(TAG, "Discovery failed: Error code:" + errorCode);mNsdManager.stopServiceDiscovery(this);}@Overridepublic 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接口,然后將其傳入方法resolveService()中,然后通過這個接口的回調方法獲得一個NsdServiceInfo對象,這個對象包含了所需要的連接信息:

public void initializeResolveListener() {mResolveListener = new NsdManager.ResolveListener() {@Overridepublic void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {// Called when the resolve fails. Use the error code to debug.Log.e(TAG, "Resolve failed" + errorCode);}@Overridepublic 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@Overrideprotected void onPause() {if (mNsdHelper != null) {mNsdHelper.tearDown();}super.onPause();}@Overrideprotected void onResume() {super.onResume();if (mNsdHelper != null) {mNsdHelper.registerService(mConnection.getLocalPort());mNsdHelper.discoverServices();}}@Overrideprotected void onDestroy() {mNsdHelper.tearDown();mConnection.tearDown();super.onDestroy();}// NsdHelper's tearDown methodpublic void tearDown() {mNsdManager.unregisterService(mRegistrationListener);mNsdManager.stopServiceDiscovery(mDiscoveryListener);}

總結

以上是生活随笔為你收集整理的Android官方开发文档Training系列课程中文版:连接无线设备之网络服务搜索功能的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。