Android中的WiFi P2P


Android中的WiFi P2P可以同意一定范圍內的設備通過Wifi直接互連而不必通過熱點或互聯網。

使用WiFi P2P須要Android API Level >= 14才干夠,並且不要忘記在Manifest文件里增加以下5個權限:

● android.permission.ACCESS_WIFI_STATE

● android.permission.CHANGE_WIFI_STATE

● android.permission.ACCESS_NETWORK_STATE

● android.permission.CHANGE_NETWORK_STATE

● android.permission.INTERNET  (WiFi P2P並不須要連接互聯網。可是由於要用到Java Socket,所以要加這個權限)


關於WiFi P2P的操作差點兒都靠WifiP2pManager來進行,所以假設你的程序要用到WiFi P2P功能,能夠設置一個全局變量wifiP2pManager,然后在onCreate()生命函數中獲取系統WifiP2pManager對象:

wifiP2pManager = (WifiP2pManager) getApplicationContext().getSystemService(Context.WIFI_P2P_SERVICE);


WifiP2pManager有例如以下方法能夠非常方便的進行P2P操作:

方法 功能
initialize() 在使用WiFi P2P功能時必須先調用這種方法,用來通過WiFi P2P框架注冊我們的應用
connect() 依據配置(WifiP2pConfig對象)與指定設備(WifiP2pDevice對象)進行P2P連接
cancelConnect() 關閉某個P2P連接
requestConnectInfo() 獲取設備的連接信息
createGroup() 以當前的設備為組長創建P2P小組
removeGroup() 移除當前的P2P小組
requestGroupInfo() 獲取P2P小組的信息
discoverPeers() 初始化peers發現操作
requestPeers() 獲取當前的peers列表(通過discoverPeers發現來的)
每當WifiP2pManager運行某個P2P操作時。能夠通過不同的監聽器來檢測這些操作的反饋結果,這些監聽器的類型例如以下:

監聽器 關聯的行為
WifiP2pManager.ActionListener connect()cancelConnect()createGroup()removeGroup()discoverPeers()
WifiP2pManager.ChannelListener initialize()
WifiP2pManager.ConnectionInfoListener requestConnectInfo()
WifiP2pManager.GroupInfoListener requestGroupInfo()
WifiP2pManager.PeerListListener requestPeers()

那么接下來就能夠解說怎樣使用WiFi P2P了。



一. 准備工作

准備階段須要讓我們的應用能夠接受P2P信號,這就須要一個意圖廣播接收器。要創建一個符合我們要求的廣播接收器須要准備以下3個要素:

(1) 一個意圖廣播接收器。用來接受意圖廣播。

(2) 通過WifiP2pManager的initialize()初始化操作來獲取一個Channel對象,用於以后和WiFi P2P框架保持通信。

(3) 自己包裝BroadcastReceiver類,實現一個接收器。


意圖過濾器使用例如以下方法創建:

// 設置intent過濾器
intentFilter = new IntentFilter();  //一個全局的intentFilter對象
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);       // WiFi P2P是否可用
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);       // peers列表發生變化
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);  // WiFi P2P連接發生變化
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); // WiFi P2P設備信息發生變化(比方更改了設備名)


Channel的獲取方法:

channel = wifiP2pManager.initialize(getApplicationContext(), getMainLooper(), null); // channel是一個全局的Channel對象

意圖廣播接收器的創建須要通過繼承BroadcastReceiver類來自己實現,以下給出了一段演示樣例:

class MyBroadcastReceiver extends BroadcastReceiver {
	// 使用WiFi P2P時。自定義的BroadcastReceiver的構造函數一定要包括以下這三個要素
	private WifiP2pManager wifiP2pManager;
	private Channel channel;
	private Activity activity;

	public MyBroadcastReceiver(WifiP2pManager wifiP2pManager, Channel channel, Activity activity) {
		this.wifiP2pManager = wifiP2pManager;
		this.channel = channel;
		this.activity = activity;
	}

	// onReceiver對對應的intent進行處理
	@Override
	public void onReceive(Context context, Intent intent) {
		String action = intent.getAction();
		if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
			int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
			if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
				// WiFi P2P 能夠使用
			} else {
				// WiFi P2P 不能夠使用
			}
		} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
		} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
		} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
		}
	}
}

定義完了之后就能夠再須要的地方實例化一個意圖廣播接收器對象了:

broadcastReceiver = new MyBroadcastReceiver(wifiP2pManager, channel, this);

那么三個要素都具備了之后就要向應用注冊我們的接收器,好讓它能夠開始工作:

registerReceiver(broadcastReceiver, intentFilter);


二. 啟動peers發現

public void discoverPeers(View view) {
	peerListListener = new WifiP2pManager.PeerListListener() {
		@Override
		public void onPeersAvailable(WifiP2pDeviceList peerList) {
			peers.clear();   // peers是一個全局ArrayList對象。用於保存發現的peers的信息
			peers.addAll(peerList.getDeviceList());
			// 假設你有一個控件用來顯示這些peers的信息,就能夠再這里更新了
		}
	};

	wifiP2pManager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
		@Override
		public void onSuccess() {
			Toast.makeText(getApplicationContext(), "discover peers!", Toast.LENGTH_SHORT);
		}

		@Override
		public void onFailure(int arg0) {
		}
	});
	// discoverPeers是異步運行的,調用了之后會立馬返回,可是發現的過程一直在進行。
	// 直到發現了某個設備時就會通知你
}


當發現了設備之后就會觸發WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION意圖廣播。你能夠再之前自己包裝的BroadcastReceiver類中增加對這一意圖的處理:

else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
	if (wifiP2pManager != null) {
		wifiP2pManager.requestPeers(channel, peerListListener);
	}
}


三. 與peers建立連接

public void connect() {
	final WifiP2pDevice device = (WifiP2pDevice) peers.get(0); //從peers列表中獲取發現來的第一個設備
	WifiP2pConfig config = new WifiP2pConfig();
	config.deviceAddress = device.deviceAddress;
	config.wps.setup = WpsInfo.PBC;

	wifiP2pManager.connect(channel, config, new WifiP2pManager.ActionListener() {
		@Override
		public void onSuccess() {
			// 連接成功
			Toast.makeText(getApplicationContext(), "與設備" + device.deviceName + "連接成功", Toast.LENGTH_LONG).show();
		}

		@Override
		public void onFailure(int arg0) {
			// 連接失敗
			Toast.makeText(getApplicationContext(), "與設備" + device.deviceName + "連接失敗", Toast.LENGTH_LONG).show();
		}
	});
}


每當有P2P連接狀態發生改變時,就會觸發WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION意圖廣播,能夠在之前你自己包裝的BroadcastReceiver類中增加對這一意圖的處理:

else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
	if (wifiP2pManager == null)
		return;

	NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
        if (networkInfo.isConnected()) {

		// We are connected with the other device, request
		// connection
		// info to find group owner IP

		wifiP2pManager.requestConnectionInfo(channel, new WifiP2pManager.ConnectionInfoListener() {
			@Override
			public void onConnectionInfoAvailable(WifiP2pInfo info) {
				// 這里能夠查看變化后的網絡信息

				// 通過傳遞進來的WifiP2pInfo參數獲取變化后的地址信息
				InetAddress groupOwnerAddress = info.groupOwnerAddress;
				// 通過協商,決定一個小組的組長
				if (info.groupFormed && info.isGroupOwner) {
					// 這里運行P2P小組組長的任務。
					// 一般是創建一個服務線程來監聽client的請求
				} else if (info.groupFormed) {
					// 這里運行普通組員的任務
					// 一般是創建一個client向組長的server發送請求
				}
			}
		});
	}
}


假設轉載請注明出處:http://blog.csdn.net/gophers




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM