Android官方开发文档Training系列课程中文版:连接无线设备之通过WIFI创建P2P连接
原文地址:http://android.xsoftlab.net/training/connect-devices-wirelessly/wifi-direct.html#permissions
Wi-Fi peer-to-peer (P2P) APIs可以使程序與附近的設(shè)備進(jìn)行直接通訊,Android的Wi-Fi P2P框架由Wi-Fi Direct?提供技術(shù)支持。WI-FI P2P技術(shù)可以使程序快速的檢索附近的設(shè)備并與之建立連接。其覆蓋范圍超過(guò)藍(lán)牙的覆蓋范圍。
這節(jié)課會(huì)學(xué)習(xí)如何通過(guò)WI-FI P2P技術(shù)搜索附近的設(shè)備并與之建立連接。
設(shè)置應(yīng)用權(quán)限
如果要使用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"/>...設(shè)置廣播接收器及P2P管理員
使用WI-FI P2P技術(shù),需要監(jiān)聽(tīng)廣播意圖,廣播意圖會(huì)通知程序某些事件的發(fā)生。所以在程序中需要添加IntentFilter,并設(shè)置其監(jiān)聽(tīng)以下行為:
WIFI\_P2P\_STATE\_CHANGED\_ACTION
監(jiān)聽(tīng)Wi-Fi P2P是否可用WIFI\_P2P\_PEERS\_CHANGED\_ACTION
監(jiān)聽(tīng)WI-FI P2P列表的變化WIFI\_P2P\_CONNECTION\_CHANGED\_ACTION
監(jiān)聽(tīng)Wi-Fi P2P的連接狀態(tài)WIFI\_P2P\_THIS\_DEVICE\_CHANGED\_ACTION
監(jiān)聽(tīng)設(shè)備的配置變化 private final IntentFilter intentFilter = new IntentFilter(); ... @Override public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);// Indicates a change in the Wi-Fi P2P status.intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);// Indicates a change in the list of available peers.intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);// Indicates the state of Wi-Fi P2P connectivity has changed.intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);// Indicates this device's details have changed.intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);... }在onCreate()方法的末尾,需要獲取WifiP2pManager的實(shí)例,然后調(diào)用它的initialize()方法。這個(gè)方法會(huì)返回一個(gè)WifiP2pManager.Channel的對(duì)象,它用于使程序應(yīng)用層與Wi-Fi P2P框架建立連接。
@Override Channel mChannel; public void onCreate(Bundle savedInstanceState) {....mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);mChannel = mManager.initialize(this, getMainLooper(), null); }接下來(lái)創(chuàng)建一個(gè)新的BroadcastReceiver類,它用于監(jiān)聽(tīng)系統(tǒng)的Wi-Fi P2P的狀態(tài)變化,在onReceive()方法中,需要添加一些基本的判斷條件來(lái)處理每種P2P的狀態(tài)并處理:
@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {// Determine if Wifi P2P mode is enabled or not, alert// the Activity.int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {activity.setIsWifiP2pEnabled(true);} else {activity.setIsWifiP2pEnabled(false);}} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {// The peer list has changed! We should probably do something about// that.} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {// Connection state changed! We should probably do something about// that.} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {DeviceListFragment fragment = (DeviceListFragment) activity.getFragmentManager().findFragmentById(R.id.frag_list);fragment.updateThisDevice((WifiP2pDevice) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE));}}最后,將廣播接收器與意圖過(guò)濾器添加到上下文中,并需要在Activity暫停的時(shí)候注銷這個(gè)廣播接收器。放置這些代碼的最佳位置就是onResume()方法與onPause()方法。
/** register the BroadcastReceiver with the intent values to be matched */@Overridepublic void onResume() {super.onResume();receiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this);registerReceiver(receiver, intentFilter);}@Overridepublic void onPause() {super.onPause();unregisterReceiver(receiver);}初始化端點(diǎn)搜索
如果開(kāi)始要使用Wi-Fi P2P來(lái)搜索附近的設(shè)備,需要調(diào)用discoverPeers()方法。這個(gè)方法要求傳入以下參數(shù):
- 在初始化P2P管理員時(shí)獲得的WifiP2pManager.Channel對(duì)象。
- WifiP2pManager.ActionListener的實(shí)現(xiàn),它用于監(jiān)聽(tīng)搜索的成功與否。
要記住,這里只是初始化了端點(diǎn)搜索。discoverPeers()方法啟動(dòng)搜索進(jìn)程后會(huì)立即返回。如果端點(diǎn)搜索進(jìn)程成功初始化,那么系統(tǒng)會(huì)自動(dòng)調(diào)用初始化時(shí)設(shè)置的回調(diào)方法。另外,端點(diǎn)搜索功能會(huì)一直保持在活動(dòng)狀態(tài),直到連接初始化完成或者P2P組建立連接。
獲取端點(diǎn)列表
接下來(lái)需要獲得并處理端點(diǎn)列表。首先需要實(shí)現(xiàn)WifiP2pManager.PeerListListener接口,它提供了WI-FI P2P所搜索到的端點(diǎn)信息。下面的代碼演示了這個(gè)過(guò)程:
private List peers = new ArrayList();...private PeerListListener peerListListener = new PeerListListener() {@Overridepublic void onPeersAvailable(WifiP2pDeviceList peerList) {// Out with the old, in with the new.peers.clear();peers.addAll(peerList.getDeviceList());// If an AdapterView is backed by this data, notify it// of the change. For instance, if you have a ListView of available// peers, trigger an update.((WiFiPeerListAdapter) getListAdapter()).notifyDataSetChanged();if (peers.size() == 0) {Log.d(WiFiDirectActivity.TAG, "No devices found");return;}}}現(xiàn)在需要修改廣播接收器的onReceive()方法,在收到WIFI\_P2P\_STATE\_CHANGED\_ACTION行為時(shí)調(diào)用requestPeers()方法。在這之前需要將監(jiān)聽(tīng)器的實(shí)例傳入到廣播接收器中,常規(guī)的方式是在廣播接收器的構(gòu)造方法中將這個(gè)監(jiān)聽(tīng)器傳進(jìn)來(lái)。、
public void onReceive(Context context, Intent intent) {...else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {// Request available peers from the wifi p2p manager. This is an// asynchronous call and the calling activity is notified with a// callback on PeerListListener.onPeersAvailable()if (mManager != null) {mManager.requestPeers(mChannel, peerListListener);}Log.d(WiFiDirectActivity.TAG, "P2P peers changed");}... }現(xiàn)在,WIFI\_P2P\_STATE\_CHANGED\_ACTION的行為將會(huì)觸發(fā)端點(diǎn)列表的更新。
連接到端點(diǎn)
為了可以連接到端點(diǎn),需要?jiǎng)?chuàng)建一個(gè)新的WifiP2pConfig對(duì)象,然后將WifiP2pDevice中的數(shù)據(jù)拷貝進(jìn)這個(gè)對(duì)象中。WifiP2pDevice代表的將要連接的設(shè)備。然后調(diào)用connect()方法。
@Overridepublic void connect() {// Picking the first device found on the network.WifiP2pDevice device = peers.get(0);WifiP2pConfig config = new WifiP2pConfig();config.deviceAddress = device.deviceAddress;config.wps.setup = WpsInfo.PBC;mManager.connect(mChannel, config, new ActionListener() {@Overridepublic void onSuccess() {// WiFiDirectBroadcastReceiver will notify us. Ignore for now.}@Overridepublic void onFailure(int reason) {Toast.makeText(WiFiDirectActivity.this, "Connect failed. Retry.",Toast.LENGTH_SHORT).show();}});}上述代碼中的WifiP2pManager.ActionListener接口只有在初始化成功或者失敗的情況下才會(huì)調(diào)用。如果要監(jiān)聽(tīng)連接狀態(tài)的變化,需要實(shí)現(xiàn)WifiP2pManager.ConnectionInfoListener接口,它的方法onConnectionInfoAvailable()會(huì)在連接狀態(tài)發(fā)生變化的時(shí)候回調(diào)。在多臺(tái)設(shè)備連接一臺(tái)設(shè)備的情況下(比如多人互動(dòng)的游戲或者聊天類的APP),其中一臺(tái)設(shè)備會(huì)被指定為”group owner”。
@Overridepublic void onConnectionInfoAvailable(final WifiP2pInfo info) {// InetAddress from WifiP2pInfo struct.InetAddress groupOwnerAddress = info.groupOwnerAddress.getHostAddress());// After the group negotiation, we can determine the group owner.if (info.groupFormed && info.isGroupOwner) {// Do whatever tasks are specific to the group owner.// One common case is creating a server thread and accepting// incoming connections.} else if (info.groupFormed) {// The other device acts as the client. In this case,// you'll want to create a client thread that connects to the group// owner.}}現(xiàn)在回到廣播接收器的onReceive()方法,修改監(jiān)聽(tīng)WIFI\_P2P\_CONNECTION\_CHANGED\_ACTION的部分,當(dāng)這個(gè)意圖接收到時(shí),調(diào)用requestConnectionInfo()方法。這是一個(gè)異步方法,所以結(jié)果會(huì)通過(guò)參數(shù):連接信息監(jiān)聽(tīng)器回調(diào)回來(lái)。
...} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {if (mManager == 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 IPmManager.requestConnectionInfo(mChannel, connectionListener);}...總結(jié)
以上是生活随笔為你收集整理的Android官方开发文档Training系列课程中文版:连接无线设备之通过WIFI创建P2P连接的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Hystrix 简介和使用
- 下一篇: 【HTML/CSS】HTML元素种类的划