注:本文翻譯自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元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
