注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術一般,由于喜愛安卓而產生了翻譯的念頭,純屬個人興趣愛好。
原文鏈接: http://developer.android.com/training/connect-devices-wirelessly/nsd-wifi-direct.html
在這系列課程的第一節課中(博客鏈接:
http://www.cnblogs.com/jdneo/p/3579936.html
),向你展示了如何發現連接到本地網絡上的服務。然而,使用Wi-Fi Peer-to-Peer(P2P)服務搜索會允許你直接發現附近設備的服務,而不需要連接到網絡中。你也可以對外廣播目前正在你的設備上運行的服務。這些功能幫助你和其它應用進行通信,甚至是當無法獲取本地網絡或者熱點的情況下。
雖然此API所要達到的目的,和之前課程中所說的NSD API非常類似,但是實現它們的代碼卻是不同的。這節課將向你展示如何使用Wi-Fi P2P從其他設備發現可獲得的服務。這節課假設你已經對 Wi-Fi P2P 的API有了一定的了解。
一). 配置清單文件
為了使用Wi-Fi P2P,需要在你的清單文件中添加 CHANGE_WIFI_STATE , ACCESS_WIFI_STATE 和 INTERNET 權限。雖然Wi-Fi P2P不需要網絡連接,但是它使用的是標準的Java套接字,而在Android中使用它們則需要聲明對應的權限許可:
<
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"
/>
...
二). 添加一個本地服務
如果你正在提供一個本地服務,你需要為服務搜索注冊它。一旦你的本地服務注冊了,框架將會自動響應Peer所發起的服務搜索請求。
要創建一個本地服務:
- 創建一個 WifiP2pServiceInfo 對象;
- 用你的服務的信息來填充它;
- 調用 addLocalService() 來為服務搜索注冊本地服務
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
}
});
}
二). 發現附近的服務
Android會使用回調函數來通知你的應用可以獲取的服務,所以要做的第一件事情就是配置它們。創建一個 WifiP2pManager.DnsSdTxtRecordListener 來監聽進入的記錄。這個記錄作為一個可選項被廣播至其它設備。當有一個記錄進來了,可以將設備地址以及其它 你想要的其它信息拷貝到一個當前方法之外的一個數據結構中,這樣你可以在之后的某一個階段去訪問它。下面的例子假設收到的記錄包含有一個“ buddyname ”字段,用以用戶身份識別。
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"
));
}
};
...
}
要獲取服務信息,創建一個 WifiP2pManager.DnsSdServiceResponseListener 。它接收了實際的描述信息和連接信息。上述代碼實現了一個 Map 對象來將“buddy name”和設備地址配對在一起。服務響應監聽器會使用它將DNS記錄和對應的服務信息連接到一起。一旦這兩個監聽器都實現了,使用 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);
...
}
現在創建一個服務請求并且調用 addServiceRequest() 。該方法必須接受一個監聽器參數來報告結果是成功的還是失敗的。
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
}
});
最后,調用 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
(...)
...
}
});
如果所有代碼都運行正常,太好了,你已經做到了!如果你遇到了問題,記住你執行的異步調用會接受一個 WifiP2pManager.ActionListener 作為參數,然后它會提供給你回調函數來指明成果或失敗。若要診斷問題所在,在 onFailure() 中添加調試代碼。該方法提供的錯誤代碼會提示問題產生的原因。下面是一些可能的錯誤值及它們的含義:
在運行程序的設備上不支持Wi-Fi P2P。
系統太忙以致無法處理請求。
由于一個內部錯誤導致操作失敗。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

