編輯:關於Android編程
原文地址:http://android.xsoftlab.net/training/connect-devices-wirelessly/nsd-wifi-direct.html
本階段的第一節課 Using Network Service Discovery 展示了如何搜索本地網絡服務。然而,使用WI-FI 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 Socket通訊技術,所以需要使用INTERNET權限:
...
如果程序提供了本地服務,還需要將該服務注冊到搜索服務中。一旦本地服務完成注冊,那麼框架會自動的響應另一端點的搜索服務請求。
創建本地網絡有以下過程:
1.創建一個WifiP2pServiceInfo對象。 2.將服務的相關信息填入其中。 3.調用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 buddies = new HashMap();
...
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記錄建立連接。一旦兩個監聽器都已經實現,那麼將它們添加到WifiP2pManager的setDnsSdResponseListeners()方法中即可。
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()方法中。方法所提供的錯誤代碼會告知問題所在。下面是可能出現的錯誤代碼以及它們的解釋:
P2P_UNSUPPORTED
當前設備不支持Wi-Fi P2P
BUSY
系統處於繁忙處理狀態
ERROR
由於內部錯誤造成操作失敗
首先是Get: 布局很簡單,就一個按鈕,主要看一下MainActivity吧: package com.francis.httpget; import android
查看類的繼承關系的快捷鍵F4,在Android Studio常用快捷鍵這篇文章中,有寫了。今天主要是講一些關於這個快捷鍵出來的界面的一些配置,這塊功能相對偏冷一些,可能
在android中,經常會和輸入法的軟件鍵盤交互。在Manifest文件裡,系統給activity的一個屬性-windowSoftInputMode來控制輸入法的顯示方式
前言隨著MVP概念的興起和發展,MVP使用越來越廣泛,當然MVP的優勢也越來越被認同,在合作開發功能模塊細分中MVP有著得天獨厚的優勢。本篇文章就來簡單的說說如何使用MV