日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

[转载]从Android源代码来看WiFi直连

發(fā)布時(shí)間:2024/3/26 Android 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转载]从Android源代码来看WiFi直连 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

什么是WiFi直連

通俗點(diǎn)說(shuō),它可以不通過(guò)網(wǎng)絡(luò),也不通過(guò)藍(lán)牙,只要兩臺(tái)設(shè)備都支持WiFi直連,打開(kāi)WiFi不用連接任何WiFi,就可以進(jìn)行信息的傳輸(請(qǐng)忽略下面兩張圖中的WiFi連接標(biāo)志,因?yàn)槠渑cWiFi的連接與否無(wú)關(guān),打開(kāi)就可以)。
在Android的設(shè)置->網(wǎng)絡(luò)與互聯(lián)網(wǎng)->WLAN->WLAN偏好設(shè)置->高級(jí)->WLAN直連中可以找到關(guān)于Wi-Fi直連的設(shè)置,如下:

在參考其它博客時(shí),寫出來(lái)的代碼并不能搜索到Wi-Fi中的其他設(shè)備,但是在這設(shè)置里面卻可以。因此,找來(lái)其Android8.0的源代碼作為參考,并成功解決問(wèn)題。

源代碼位置:

  • /packages/apps/Settings/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
  • 在線Android8.0 WiFi直連相關(guān)源代碼

我們可以通過(guò)系統(tǒng)的源代碼來(lái)了解其相應(yīng)的API的使用。下面是對(duì)應(yīng)的系統(tǒng)源代碼的分析:


注冊(cè)權(quán)限

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/> <uses-permission android:name="android.permission.INTERNET"/>
  • 1
  • 2
  • 3
  • 4
  • 5

廣播的接收與處理

在onResume()中注冊(cè)廣播接收,在onPause()中取消廣播接收。

/** * Broadcast intent action to indicate whether Wi-Fi p2p is enabled or disabled. An * extra {@link #EXTRA_WIFI_STATE} provides the state information as int. * * @see #EXTRA_WIFI_STATE */ mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);/** * Broadcast intent action indicating that the available peer list has changed. This * can be sent as a result of peers being found, lost or updated. * * <p> An extra {@link #EXTRA_P2P_DEVICE_LIST} provides the full list of * current peers. The full list of peers can also be obtained any time with * {@link #requestPeers}. * * @see #EXTRA_P2P_DEVICE_LIST */ mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);/** * Broadcast intent action indicating that the state of Wi-Fi p2p connectivity * has changed. One extra {@link #EXTRA_WIFI_P2P_INFO} provides the p2p connection info in * the form of a {@link WifiP2pInfo} object. Another extra {@link #EXTRA_NETWORK_INFO} provides * the network info in the form of a {@link android.net.NetworkInfo}. A third extra provides * the details of the group. * * @see #EXTRA_WIFI_P2P_INFO * @see #EXTRA_NETWORK_INFO * @see #EXTRA_WIFI_P2P_GROUP */ mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);/** * Broadcast intent action indicating that this device details have changed. */ mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);/** * Broadcast intent action indicating that peer discovery has either started or stopped. * One extra {@link #EXTRA_DISCOVERY_STATE} indicates whether discovery has started * or stopped. * * <p>Note that discovery will be stopped during a connection setup. If the application tries * to re-initiate discovery during this time, it can fail. */ mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);/** * Broadcast intent action indicating that remembered persistent groups have changed. * @hide */ mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

對(duì)上面廣播的處理(需要留意的是,這些數(shù)據(jù)都是從Intent中取出來(lái)的):

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {mWifiP2pEnabled = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE,WifiP2pManager.WIFI_P2P_STATE_DISABLED) == WifiP2pManager.WIFI_P2P_STATE_ENABLED;handleP2pStateChanged();} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {// 這里是直接從Intent中取出了列表數(shù)據(jù)mPeers = (WifiP2pDeviceList) intent.getParcelableExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST);handlePeersChanged();} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {if (mWifiP2pManager == null) return;NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);// 此處的WifiP2pInfo可以讓我們獲取到GO(Group Owner)的IP// 這是最神奇的地方,沒(méi)有網(wǎng)絡(luò)的連接,卻得到了IP// 然后我們可以通過(guò)這個(gè)IP,與GO進(jìn)行socket通信WifiP2pInfo wifip2pinfo = (WifiP2pInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);if (networkInfo.isConnected()) {if (DBG) Log.d(TAG, "Connected");} else if (mLastGroupFormed != true) {//start a search when we are disconnected//but not on group removed broadcast eventstartSearch();}mLastGroupFormed = wifip2pinfo.groupFormed;} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {mThisDevice = (WifiP2pDevice) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);if (DBG) Log.d(TAG, "Update device info: " + mThisDevice);updateDevicePref();} else if (WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION.equals(action)) {int discoveryState = intent.getIntExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE,WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED);if (DBG) Log.d(TAG, "Discovery state changed: " + discoveryState);if (discoveryState == WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED) {updateSearchMenu(true);} else {updateSearchMenu(false);}} else if (WifiP2pManager.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION.equals(action)) {if (mWifiP2pManager != null) {mWifiP2pManager.requestPersistentGroupInfo(mChannel, WifiP2pSettings.this);}}} };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

點(diǎn)擊搜索

點(diǎn)擊菜單欄上的搜索后,會(huì)進(jìn)行如下操作。然后會(huì)接收到相應(yīng)的廣播,刷新是在對(duì)相應(yīng)廣播的處理中進(jìn)行的。

private void startSearch() {if (mWifiP2pManager != null && !mWifiP2pSearching) {mWifiP2pManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {public void onSuccess() {}public void onFailure(int reason) {if (DBG) Log.d(TAG, " discover fail " + reason);}});} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在對(duì)廣播的處理中,設(shè)備變化的處理主要是靠handlePeersChanged():

private void handlePeersChanged() {mPeersGroup.removeAll();mConnectedDevices = 0;if (DBG) Log.d(TAG, "List of available peers");for (WifiP2pDevice peer: mPeers.getDeviceList()) {if (DBG) Log.d(TAG, "-> " + peer);mPeersGroup.addPreference(new WifiP2pPeer(getActivity(), peer));if (peer.status == WifiP2pDevice.CONNECTED) mConnectedDevices++;}if (DBG) Log.d(TAG, " mConnectedDevices " + mConnectedDevices); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

連接設(shè)備或斷開(kāi)連接

  • 連接設(shè)備
WifiP2pConfig config = new WifiP2pConfig(); config.deviceAddress = mSelectedWifiPeer.device.deviceAddress;int forceWps = SystemProperties.getInt("wifidirect.wps", -1);if (forceWps != -1) {config.wps.setup = forceWps; } else {if (mSelectedWifiPeer.device.wpsPbcSupported()) {config.wps.setup = WpsInfo.PBC;} else if (mSelectedWifiPeer.device.wpsKeypadSupported()) {config.wps.setup = WpsInfo.KEYPAD;} else {config.wps.setup = WpsInfo.DISPLAY;} }mWifiP2pManager.connect(mChannel, config,new WifiP2pManager.ActionListener() {public void onSuccess() {if (DBG) Log.d(TAG, " connect success");}public void onFailure(int reason) {Log.e(TAG, " connect fail " + reason);Toast.makeText(getActivity(),R.string.wifi_p2p_failed_connect_message,Toast.LENGTH_SHORT).show();}});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

對(duì)這段代碼中,有一個(gè)使用了android.os.SystemProperties這個(gè){@hide}修飾的類。我們可以考慮通過(guò)反射的方式來(lái)近行調(diào)用,如下:

private int getSystemProp(){try {Class<?> cls = Class.forName("android.os.SystemProperties");Method m = cls.getDeclaredMethod("get", String.class, String.class);return Integer.parseInt((String)m.invoke(null,"wifidirect.wps","-1"));} catch (Exception e) {Log.i(TAG, "E = " + e.getMessage());e.printStackTrace();}return -1; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 斷開(kāi)連接
//disconnect dialog listener mDisconnectListener = new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {if (which == DialogInterface.BUTTON_POSITIVE) {if (mWifiP2pManager != null) {mWifiP2pManager.removeGroup(mChannel, new WifiP2pManager.ActionListener() {public void onSuccess() {if (DBG) Log.d(TAG, " remove group success");}public void onFailure(int reason) {if (DBG) Log.d(TAG, " remove group fail " + reason);}});}}} };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 取消已發(fā)送的邀請(qǐng)
//cancel connect dialog listener mCancelConnectListener = new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {if (which == DialogInterface.BUTTON_POSITIVE) {if (mWifiP2pManager != null) {mWifiP2pManager.cancelConnect(mChannel,new WifiP2pManager.ActionListener() {public void onSuccess() {if (DBG) Log.d(TAG, " cancel connect success");}public void onFailure(int reason) {if (DBG) Log.d(TAG, " cancel connect fail " + reason);}});}}} };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

重命名設(shè)備名稱

mRenameListener = new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {if (which == DialogInterface.BUTTON_POSITIVE) {if (mWifiP2pManager != null) {String name = mDeviceNameText.getText().toString();if (name != null) {for (int i = 0; i < name.length(); i++) {char cur = name.charAt(i);if(!Character.isDigit(cur) && !Character.isLetter(cur)&& cur != '-' && cur != '_' && cur != ' ') {Toast.makeText(getActivity(),R.string.wifi_p2p_failed_rename_message,Toast.LENGTH_LONG).show();return;}}}mWifiP2pManager.setDeviceName(mChannel,mDeviceNameText.getText().toString(),new WifiP2pManager.ActionListener() {public void onSuccess() {if (DBG) Log.d(TAG, " device rename success");}public void onFailure(int reason) {Toast.makeText(getActivity(),R.string.wifi_p2p_failed_rename_message,Toast.LENGTH_LONG).show();}});}}} };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

如何進(jìn)行信息的傳輸?

對(duì)于GO來(lái)說(shuō),當(dāng)與GC(Group Client)連接完成后,也就是接收到WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION廣播后,需要充當(dāng)?shù)慕巧欠?wù)器,所以可以利用Java中socket通信中的SocketServer來(lái)阻塞當(dāng)前的線程(子),監(jiān)聽(tīng)所受到的socket。如下:

if (wifip2pinfoG.isGroupOwner) { // 充當(dāng)服務(wù)器new Thread(new Runnable() {// 不能阻塞主線程@Override // 同時(shí)也不允許在主線程中進(jìn)行網(wǎng)絡(luò)通信public void run() { // 所以開(kāi)啟子線程try {ServerSocket server = new ServerSocket(6666, 100, wifip2pinfoG.groupOwnerAddress);Socket socket;while((socket = server.accept()) != null){InputStream bis = socket.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(bis));String info = br.readLine();final String log = info;// 顯示出所接收的信息Log.e("TAG", log);MainActivity.this.runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(context, log, Toast.LENGTH_SHORT).show();}});}} catch (IOException e) {e.printStackTrace();}}}).start();Toast.makeText(context, "服務(wù)器已啟動(dòng)", Toast.LENGTH_SHORT).show(); } else { // 充當(dāng)客戶端Toast.makeText(context, "可發(fā)送消息", Toast.LENGTH_SHORT).show(); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

對(duì)GC來(lái)說(shuō),當(dāng)與GO連接好了之后,即可發(fā)送給GO發(fā)送消息。如下:

new Thread(new Runnable() {// 不能在主線程中進(jìn)行網(wǎng)絡(luò)通信,需要子線程@Overridepublic void run() {try {sendSocket = new Socket(wifip2pinfoG.groupOwnerAddress, 6666);OutputStreamWriter osw = new OutputStreamWriter(sendSocket.getOutputStream());// getInfo()是一個(gè)輸入框,沒(méi)有輸入時(shí)默認(rèn)返回helloosw.write(getInfo());osw.flush();Log.e("TAG", "info sended");// 注意這里,需要及時(shí)關(guān)閉socketsendSocket.close();} catch (IOException e) {e.printStackTrace();}} }).start();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-526ced5128.css" rel="stylesheet"></div>

總結(jié)

以上是生活随笔為你收集整理的[转载]从Android源代码来看WiFi直连的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。