Android官方开发文档Training系列课程中文版:连接无线设备之通过P2P搜索网络服务
原文地址:http://android.xsoftlab.net/training/connect-devices-wirelessly/nsd-wifi-direct.html
本階段的第一節(jié)課 Using Network Service Discovery 展示了如何搜索本地網(wǎng)絡(luò)服務(wù)。然而,使用WI-FI P2P搜索服務(wù)可以直接搜索附近的設(shè)備,而不需要專門通過(guò)本地網(wǎng)絡(luò)。這項(xiàng)特性使得在沒有本地網(wǎng)絡(luò)或者熱點(diǎn)的情況下還可以在不同的設(shè)備間進(jìn)行通信。
雖然這里的API與NSD的API的目的很相似,但是實(shí)現(xiàn)的過(guò)程卻完全不同。這節(jié)課展示了如何通過(guò)WI-FI P2P網(wǎng)絡(luò)來(lái)搜索附近的可用服務(wù)。這節(jié)課建立在已經(jīng)對(duì)Wi-Fi P2P API熟悉的基礎(chǔ)之上。
設(shè)置清單文件
如果要使用WI-FI P2P技術(shù),需要在程序的清單文件中添加CHANGE_WIFI_STATE, ACCESS_WIFI_STATE, INTERNET三項(xiàng)權(quán)限。雖然Wi-Fi P2P并不需要互聯(lián)網(wǎng)連接,但是它需要使用標(biāo)準(zhǔn)的Java Socket通訊技術(shù),所以需要使用INTERNET權(quán)限:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.android.nsdchat"...<uses-permissionandroid: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"/>...添加本地服務(wù)
如果程序提供了本地服務(wù),還需要將該服務(wù)注冊(cè)到搜索服務(wù)中。一旦本地服務(wù)完成注冊(cè),那么框架會(huì)自動(dòng)的響應(yīng)另一端點(diǎn)的搜索服務(wù)請(qǐng)求。
創(chuàng)建本地網(wǎng)絡(luò)有以下過(guò)程:
- 1.創(chuàng)建一個(gè)WifiP2pServiceInfo對(duì)象。
- 2.將服務(wù)的相關(guān)信息填入其中。
- 3.調(diào)用addLocalService()方法完成本地服務(wù)注冊(cè)。
搜索附近的服務(wù)
Android會(huì)使用回調(diào)方法來(lái)通知應(yīng)用程序有可用的服務(wù),所以首先要做的就是設(shè)置該回調(diào)。創(chuàng)建一個(gè)WifiP2pManager.DnsSdTxtRecordListener來(lái)監(jiān)聽傳入的記錄。這個(gè)記錄由其它設(shè)備隨意廣播。當(dāng)其中一條記錄到達(dá)時(shí),會(huì)將該設(shè)備的地址及其它相關(guān)的信息拷貝到一個(gè)外部的數(shù)據(jù)結(jié)構(gòu)中,這樣的話就可以晚一些訪問(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ù)的相關(guān)信息,需要?jiǎng)?chuàng)建一個(gè)WifiP2pManager.DnsSdServiceResponseListener接口。 這個(gè)接口會(huì)接收實(shí)際的連接信息。上面代碼段中的Map對(duì)象將設(shè)備的地址與”buddy name”組成了鍵值對(duì)。服務(wù)響應(yīng)監(jiān)聽器利用這項(xiàng)特性與DNS記錄建立連接。一旦兩個(gè)監(jiān)聽器都已經(jīng)實(shí)現(xiàn),那么將它們添加到WifiP2pManager的setDnsSdResponseListeners()方法中即可。
private void discoverService() { ...DnsSdServiceResponseListener servListener = new DnsSdServiceResponseListener() {@Overridepublic 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);... }接下來(lái)需要?jiǎng)?chuàng)建一個(gè)新的服務(wù)請(qǐng)求,然后將其作為參數(shù)調(diào)用addServiceRequest()方法,這個(gè)方法同樣需要一個(gè)監(jiān)聽器來(lái)反應(yīng)成功還是失敗。
serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();mManager.addServiceRequest(channel,serviceRequest,new ActionListener() {@Overridepublic void onSuccess() {// Success!}@Overridepublic void onFailure(int code) {// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY}});最后,調(diào)用discoverServices()方法開始搜索服務(wù)。
mManager.discoverServices(channel, new ActionListener() {@Overridepublic void onSuccess() {// Success!}@Overridepublic void onFailure(int code) {// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSYif (code == WifiP2pManager.P2P_UNSUPPORTED) {Log.d(TAG, "P2P isn't supported on this device.");else if(...)...}});如果上面的都已經(jīng)完成,那么可以喊一聲哈利路亞了,已經(jīng)完成了所有的步驟。如果遇到了問(wèn)題,尋找那個(gè)將WifiP2pManager.ActionListener作為參數(shù)的方法,這個(gè)回調(diào)方法會(huì)告知程序是成功還是失敗。如果要解決這個(gè)問(wèn)題,請(qǐng)將調(diào)試代碼放入onFailure()方法中。方法所提供的錯(cuò)誤代碼會(huì)告知問(wèn)題所在。下面是可能出現(xiàn)的錯(cuò)誤代碼以及它們的解釋:
P2P_UNSUPPORTED
當(dāng)前設(shè)備不支持Wi-Fi P2PBUSY
系統(tǒng)處于繁忙處理狀態(tài)ERROR
由于內(nèi)部錯(cuò)誤造成操作失敗總結(jié)
以上是生活随笔為你收集整理的Android官方开发文档Training系列课程中文版:连接无线设备之通过P2P搜索网络服务的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android官方开发文档Trainin
- 下一篇: Tensorflow修改张量特定位置元素