注:本文翻譯自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非常類似,但是實(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ì)您有幫助就好】元

