注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術(shù)一般,由于喜愛(ài)安卓而產(chǎn)生了翻譯的念頭,純屬個(gè)人興趣愛(ài)好。
原文鏈接: http://developer.android.com/training/connect-devices-wirelessly/nsd-wifi-direct.html
在這系列課程的第一節(jié)課中(博客鏈接:
http://www.cnblogs.com/jdneo/p/3579936.html
),向你展示了如何發(fā)現(xiàn)連接到本地網(wǎng)絡(luò)上的服務(wù)。然而,使用Wi-Fi Peer-to-Peer(P2P)服務(wù)搜索會(huì)允許你直接發(fā)現(xiàn)附近設(shè)備的服務(wù),而不需要連接到網(wǎng)絡(luò)中。你也可以對(duì)外廣播目前正在你的設(shè)備上運(yùn)行的服務(wù)。這些功能幫助你和其它應(yīng)用進(jìn)行通信,甚至是當(dāng)無(wú)法獲取本地網(wǎng)絡(luò)或者熱點(diǎn)的情況下。
雖然此API所要達(dá)到的目的,和之前課程中所說(shuō)的NSD API非常類(lèi)似,但是實(shí)現(xiàn)它們的代碼卻是不同的。這節(jié)課將向你展示如何使用Wi-Fi P2P從其他設(shè)備發(fā)現(xiàn)可獲得的服務(wù)。這節(jié)課假設(shè)你已經(jīng)對(duì) Wi-Fi P2P 的API有了一定的了解。
一). 配置清單文件
為了使用Wi-Fi P2P,需要在你的清單文件中添加 CHANGE_WIFI_STATE , ACCESS_WIFI_STATE 和 INTERNET 權(quán)限。雖然Wi-Fi P2P不需要網(wǎng)絡(luò)連接,但是它使用的是標(biāo)準(zhǔn)的Java套接字,而在Android中使用它們則需要聲明對(duì)應(yīng)的權(quán)限許可:
< 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" /> ...
二). 添加一個(gè)本地服務(wù)
如果你正在提供一個(gè)本地服務(wù),你需要為服務(wù)搜索注冊(cè)它。一旦你的本地服務(wù)注冊(cè)了,框架將會(huì)自動(dòng)響應(yīng)Peer所發(fā)起的服務(wù)搜索請(qǐng)求。
要?jiǎng)?chuàng)建一個(gè)本地服務(wù):
- 創(chuàng)建一個(gè) WifiP2pServiceInfo 對(duì)象;
- 用你的服務(wù)的信息來(lái)填充它;
- 調(diào)用 addLocalService() 來(lái)為服務(wù)搜索注冊(cè)本地服務(wù)
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 } }); }
二). 發(fā)現(xiàn)附近的服務(wù)
Android會(huì)使用回調(diào)函數(shù)來(lái)通知你的應(yīng)用可以獲取的服務(wù),所以要做的第一件事情就是配置它們。創(chuàng)建一個(gè) WifiP2pManager.DnsSdTxtRecordListener 來(lái)監(jiān)聽(tīng)進(jìn)入的記錄。這個(gè)記錄作為一個(gè)可選項(xiàng)被廣播至其它設(shè)備。當(dāng)有一個(gè)記錄進(jìn)來(lái)了,可以將設(shè)備地址以及其它 你想要的其它信息拷貝到一個(gè)當(dāng)前方法之外的一個(gè)數(shù)據(jù)結(jié)構(gòu)中,這樣你可以在之后的某一個(gè)階段去訪問(wèn)它。下面的例子假設(shè)收到的記錄包含有一個(gè)“ buddyname ”字段,用以用戶身份識(shí)別。
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" )); } }; ... }
要獲取服務(wù)信息,創(chuàng)建一個(gè) WifiP2pManager.DnsSdServiceResponseListener 。它接收了實(shí)際的描述信息和連接信息。上述代碼實(shí)現(xiàn)了一個(gè) Map 對(duì)象來(lái)將“buddy name”和設(shè)備地址配對(duì)在一起。服務(wù)響應(yīng)監(jiān)聽(tīng)器會(huì)使用它將DNS記錄和對(duì)應(yīng)的服務(wù)信息連接到一起。一旦這兩個(gè)監(jiān)聽(tīng)器都實(shí)現(xiàn)了,使用 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); ... }
現(xiàn)在創(chuàng)建一個(gè)服務(wù)請(qǐng)求并且調(diào)用 addServiceRequest() 。該方法必須接受一個(gè)監(jiān)聽(tīng)器參數(shù)來(lái)報(bào)告結(jié)果是成功的還是失敗的。
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 } });
最后,調(diào)用 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 (...) ... } });
如果所有代碼都運(yùn)行正常,太好了,你已經(jīng)做到了!如果你遇到了問(wèn)題,記住你執(zhí)行的異步調(diào)用會(huì)接受一個(gè) WifiP2pManager.ActionListener 作為參數(shù),然后它會(huì)提供給你回調(diào)函數(shù)來(lái)指明成果或失敗。若要診斷問(wèn)題所在,在 onFailure() 中添加調(diào)試代碼。該方法提供的錯(cuò)誤代碼會(huì)提示問(wèn)題產(chǎn)生的原因。下面是一些可能的錯(cuò)誤值及它們的含義:
在運(yùn)行程序的設(shè)備上不支持Wi-Fi P2P。
系統(tǒng)太忙以致無(wú)法處理請(qǐng)求。
由于一個(gè)內(nèi)部錯(cuò)誤導(dǎo)致操作失敗。
【Android Developers Training】 77. 使用Wi-Fi P2P進(jìn)行服務(wù)搜索
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(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ì)您有幫助就好】元
