WifiP2pSettings工作流程

来源:互联网 发布:网络招生技巧 编辑:程序博客网 时间:2024/06/08 07:02
Android平台中,P2P操作用户只需执行如下三个步骤:
1)进入WifiP2pSettings界面;
2)搜索周围的P2P设备。搜索到的设备将显示在WifiP2pSettings中。
3)用户选择其中的某个设备以发起连接。
首先来看WifiP2pSettings的onActivityCreate函数。
1.WifiP2pSettings创建

Android-5.1/packages/apps/Settings/src/com/android/settings/wifi/p2p/WifiP2pSettings.Java

[cpp] view plain copy
  1.    public void onActivityCreated(Bundle savedInstanceState) {  
  2.        addPreferencesFromResource(R.xml.wifi_p2p_settings);//加载界面元素  
  3. /*WifiP2pSettings也是通过监听广播的方式来了解系统中Wi-Fi P2P相关的信息及变化情况。下面这几个广播属于P2P特有的,其作用如下:  
  4. WIFI_P2P_STATE_CHANGED_ACTION:用于通知系统中P2P功能的启用情况,如该功能是enable还是disable。  
  5. WIFI_P2P_PEERS_CHANGED_ACTION:系统内部将保存搜索到的其他P2P设备信息,如果这些信息有变化,则系统将发送该广播。接收者需要通过WifiP2PManager的requestPeers函数重新获取这些P2P设备的信息。  
  6. WIFI_P2P_CONNECTION_CHANGED_ACTION:用于通知P2P连接情况,该广播可携带WifiP2pInfo和NetworkInfo两个对象。相关信息可从这两个对象中获取。  
  7. WIFI_P2P_THIS_DEVICE_CHANGED_ACTION:用于通知本机P2P设备信息发生了变化。  
  8. WIFI_P2P_DISCOVERY_CHANGED_ACTION:用于通知P2P Device Discovery的工作状态,如启动或停止。  
  9. WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION:用于通知persistent group信息发生了变化。  
  10.        mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);  
  11.        mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);  
  12.        mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);  
  13.        mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);  
  14.        mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);  
  15.        mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION);  
  16.   
  17.        final Activity activity = getActivity();  
  18.     //创建WifiP2pManager对象,它将和WifiP2pService交互  
  19.        mWifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);  
  20.        if (mWifiP2pManager != null) {  
  21.         //初始化WifiManager并建立和WiFiService的联系  
  22.            mChannel = mWifiP2pManager.initialize(activity, getActivity().getMainLooper(), null);  
  23.            if (mChannel == null) {  
  24.                //Failure to set up connection  
  25.                Log.e(TAG, "Failed to set up connection with wifi p2p service");  
  26.                mWifiP2pManager = null;  
  27.            }  
  28.        } else {  
  29.            Log.e(TAG, "mWifiP2pManager is null !");  
  30.        }  
  31.   
  32.        if (savedInstanceState != null && savedInstanceState.containsKey(SAVE_DIALOG_PEER)) {  
  33.            WifiP2pDevice device = savedInstanceState.getParcelable(SAVE_DIALOG_PEER);  
  34.            mSelectedWifiPeer = new WifiP2pPeer(getActivity(), device);  
  35.        }  
  36.        if (savedInstanceState != null && savedInstanceState.containsKey(SAVE_DEVICE_NAME)) {  
  37.            mSavedDeviceName = savedInstanceState.getString(SAVE_DEVICE_NAME);  
  38.        }  
  39.        if (savedInstanceState != null && savedInstanceState.containsKey(SAVE_SELECTED_GROUP)) {  
  40.            mSelectedGroupName = savedInstanceState.getString(SAVE_SELECTED_GROUP);  
  41.        }  
  42.   
  43.     //创建UI中按钮对应的onClickListener  
  44.        mRenameListener = new OnClickListener() {  
  45.            @Override  
  46.            public void onClick(DialogInterface dialog, int which) {  
  47.                if (which == DialogInterface.BUTTON_POSITIVE) {  
  48.                    if (mWifiP2pManager != null) {  
  49.                        mWifiP2pManager.setDeviceName(mChannel,  
  50.                                mDeviceNameText.getText().toString(),  
  51.                                new WifiP2pManager.ActionListener() {  
  52.                            public void onSuccess() {  
  53.                                if (DBG) Log.d(TAG, " device rename success");  
  54.                            }  
  55.                            public void onFailure(int reason) {  
  56.                                Toast.makeText(getActivity(),  
  57.                                        R.string.wifi_p2p_failed_rename_message,  
  58.                                        Toast.LENGTH_LONG).show();  
  59.                            }  
  60.                        });  
  61.                    }  
  62.                }  
  63.            }  
  64.        };  
  65.   
  66.        //disconnect dialog listener  
  67.        mDisconnectListener = new OnClickListener() {  
  68.            @Override  
  69.            public void onClick(DialogInterface dialog, int which) {  
  70.                if (which == DialogInterface.BUTTON_POSITIVE) {  
  71.                    if (mWifiP2pManager != null) {  
  72.                        mWifiP2pManager.removeGroup(mChannel, new WifiP2pManager.ActionListener() {  
  73.                            public void onSuccess() {  
  74.                                if (DBG) Log.d(TAG, " remove group success");  
  75.                            }  
  76.                            public void onFailure(int reason) {  
  77.                                if (DBG) Log.d(TAG, " remove group fail " + reason);  
  78.                            }  
  79.                        });  
  80.                    }  
  81.                }  
  82.            }  
  83.        };  
  84.   
  85.        //cancel connect dialog listener  
  86.        mCancelConnectListener = new OnClickListener() {  
  87.            @Override  
  88.            public void onClick(DialogInterface dialog, int which) {  
  89.                if (which == DialogInterface.BUTTON_POSITIVE) {  
  90.                    if (mWifiP2pManager != null) {  
  91.                        mWifiP2pManager.cancelConnect(mChannel,  
  92.                                new WifiP2pManager.ActionListener() {  
  93.                            public void onSuccess() {  
  94.                                if (DBG) Log.d(TAG, " cancel connect success");  
  95.                            }  
  96.                            public void onFailure(int reason) {  
  97.                                if (DBG) Log.d(TAG, " cancel connect fail " + reason);  
  98.                            }  
  99.                        });  
  100.                    }  
  101.                }  
  102.            }  
  103.        };  
  104.   
  105.        //delete persistent group dialog listener  
  106.        mDeleteGroupListener = new OnClickListener() {  
  107.            @Override  
  108.            public void onClick(DialogInterface dialog, int which) {  
  109.                if (which == DialogInterface.BUTTON_POSITIVE) {  
  110.                    if (mWifiP2pManager != null) {  
  111.                        if (mSelectedGroup != null) {  
  112.                            if (DBG) Log.d(TAG, " deleting group " + mSelectedGroup.getGroupName());  
  113.                            mWifiP2pManager.deletePersistentGroup(mChannel,  
  114.                                    mSelectedGroup.getNetworkId(),  
  115.                                    new WifiP2pManager.ActionListener() {  
  116.                                public void onSuccess() {  
  117.                                    if (DBG) Log.d(TAG, " delete group success");  
  118.                                }  
  119.                                public void onFailure(int reason) {  
  120.                                    if (DBG) Log.d(TAG, " delete group fail " + reason);  
  121.                                }  
  122.                            });  
  123.                            mSelectedGroup = null;  
  124.                        } else {  
  125.                            if (DBG) Log.w(TAG, " No selected group to delete!" );  
  126.                        }  
  127.                    }  
  128.                } else if (which == DialogInterface.BUTTON_NEGATIVE) {  
  129.                    if (DBG) {  
  130.                        Log.d(TAG, " forgetting selected group " + mSelectedGroup.getGroupName());  
  131.                    }  
  132.                    mSelectedGroup = null;  
  133.                }  
  134.            }  
  135.        };  
  136.   
  137.        setHasOptionsMenu(true);  
  138.   
  139.        final PreferenceScreen preferenceScreen = getPreferenceScreen();  
  140.        preferenceScreen.removeAll();  
  141.        preferenceScreen.setOrderingAsAdded(true);  
  142.   
  143.        mThisDevicePref = new Preference(getActivity());  
  144.        mThisDevicePref.setPersistent(false);  
  145.        mThisDevicePref.setSelectable(false);  
  146.        preferenceScreen.addPreference(mThisDevicePref);  
  147.   
  148.        mPeersGroup = new PreferenceCategory(getActivity());  
  149.        mPeersGroup.setTitle(R.string.wifi_p2p_peer_devices);  
  150.        preferenceScreen.addPreference(mPeersGroup);  
  151.   
  152.        mPersistentGroup = new PreferenceCategory(getActivity());  
  153.        mPersistentGroup.setTitle(R.string.wifi_p2p_remembered_groups);  
  154.        preferenceScreen.addPreference(mPersistentGroup);  
  155.   
  156.        super.onActivityCreated(savedInstanceState);  
  157.    }  

2.WifiP2pSettings工作流程
1)WIFI_P2P_STATE_CHANGED_ACTION处理流程
打开WifiP2pSettings后,首先要等待 WIFI_P2P_STATE_CHANGED_ACTION广播以判断P2P功能是否正常启动。相应的处理函数如下所示:
android-5.1/packages/apps/Settings/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
[cpp] view plain copy
  1. private final BroadcastReceiver mReceiver = new BroadcastReceiver() {  
  2.     @Override  
  3.     public void onReceive(Context context, Intent intent) {  
  4.         String action = intent.getAction();  
  5.   
  6.         if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {  
  7. //从 WIFI_P2P_STATE_CHANGED_ACTION广播中获取相关状态信息以判断P2P功能是否打开  
  8.             mWifiP2pEnabled = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE,  
  9.                 WifiP2pManager.WIFI_P2P_STATE_DISABLED) == WifiP2pManager.WIFI_P2P_STATE_ENABLED;  
  10.             handleP2pStateChanged();  
  11. /如果搜索到新的P2P设备,则WIFI_P2P_PEERS_CHANGED_ACTION将被发送  
  12.         } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {  
  13.             mPeers = (WifiP2pDeviceList) intent.getParcelableExtra(  
  14.                     WifiP2pManager.EXTRA_P2P_DEVICE_LIST);  
  15.             handlePeersChanged();  
  16.         } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {  
  17.             if (mWifiP2pManager == null) return;  
  18.             NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(  
  19.                     WifiP2pManager.EXTRA_NETWORK_INFO);  
  20.             WifiP2pInfo wifip2pinfo = (WifiP2pInfo) intent.getParcelableExtra(  
  21.                     WifiP2pManager.EXTRA_WIFI_P2P_INFO);  
  22.             if (networkInfo.isConnected()) {  
  23.                 if (DBG) Log.d(TAG, "Connected");  
  24.             } else if (mLastGroupFormed != true) {  
  25.                 //start a search when we are disconnected  
  26.                 //but not on group removed broadcast event  
  27.                 startSearch();  //如果没有加入某个P2P组,则重新发起设备扫描  
  28.             }  
  29.             mLastGroupFormed = wifip2pinfo.groupFormed;  
  30.         } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {  
  31.             mThisDevice = (WifiP2pDevice) intent.getParcelableExtra(  
  32.                     WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);  
  33.             if (DBG) Log.d(TAG, "Update device info: " + mThisDevice);  
  34.             updateDevicePref();  
  35.         } else if (WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION.equals(action)) {  
  36.             int discoveryState = intent.getIntExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE,  
  37.                 WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED);  
  38.             if (DBG) Log.d(TAG, "Discovery state changed: " + discoveryState);  
  39.             if (discoveryState == WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED) {  
  40.                 updateSearchMenu(true);//更新SEARCH按钮显示的名称  
  41.             } else {  
  42.                 updateSearchMenu(false);  
  43.             }  
  44.         } else if (WifiP2pManager.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION.equals(action)) {  
  45.             if (mWifiP2pManager != null) {  
  46.                 mWifiP2pManager.requestPersistentGroupInfo(mChannel, WifiP2pSettings.this);  
  47.             }  
  48.         }  
  49.     }  
  50. };  

[cpp] view plain copy
  1. private void handleP2pStateChanged() {  
  2.     updateSearchMenu(false);//该函数将触发WifiP2pSettings的onCreateOptionsMenu被调用  
  3.     mThisDevicePref.setEnabled(mWifiP2pEnabled);  
  4.     mPeersGroup.setEnabled(mWifiP2pEnabled);  
  5.     mPersistentGroup.setEnabled(mWifiP2pEnabled);  
  6. }  
用户下一步要做的事情就是主动搜索周围的P2P设备。Android原生代码中的WifiP2pSettings界面下方有两个按钮,分别是SEARCH和RENAME,分别用于搜索周围的P2P Device和更改本机的P2P设备名。
当P2P功能正常启用后(即上述代码中的mWifiP2pEnabled为true时),这两个按钮将被使能。此后,用户就可单击SEARCH按钮以搜索周围的P2P设备。该按钮对应的函数是startSearch。
[cpp] view plain copy
  1.  private void startSearch() {  
  2.      if (mWifiP2pManager != null && !mWifiP2pSearching) {  
  3. //discoverPeers将搜索周围的P2P设备  
  4.          mWifiP2pManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {  
  5.              public void onSuccess() {  
  6.              }  
  7.              public void onFailure(int reason) {  
  8.                  if (DBG) Log.d(TAG, " discover fail " + reason);  
  9.              }  
  10.          });  
  11.      }  
  12.  }  
当WPAS完成搜索后, WIFI_P2P_PEERS_CHANGED_ACTION广播将被发送。对该广播的处理参考onReceive函数。startSearch还将触发系统发送 WIFI_P2P_DISCOVERY_CHANGED_ACTION广播,WifiP2pSettings将根据该广播携带的信息来更新SEARCH按钮的界面:如果P2P Discovery启动成功(即状态变为 WIFI_P2P_DISCOVERY_STARTED),则SEARCH按钮名称显示为Searching,否则该按钮显示为Search For Devices。
当系统搜索到新的P2P设备后,WIFI_P2P_PEERS_CHANGED_ACTION广播将被发送,而WifiP2pSettings对于该广播的处理就是调用WifiP2pManager的requestPeers来获取系统保存的P2P设备信息列表
系统中所有的P2P设备信息将通过PeerListener接口类的onPeersAvailable函数返回给WifiP2pSettings:
[cpp] view plain copy
  1.   public void onPeersAvailable(WifiP2pDeviceList peers) {  
  2.       if (DBG) Log.d(TAG, "Requested peers are available");  
  3. //系统中所有的P2P设备信息都保存在这个类型为WifiP2pDeviceList的peers对象中  
  4.       mPeers = peers;  
  5.       handlePeersChanged();  
  6.   }  

[cpp] view plain copy
  1.  private void handlePeersChanged() {  
  2.      mPeersGroup.removeAll();//mPeersGroup类型为PreferenceGroup,属于UI相关的类  
  3.   
  4.      mConnectedDevices = 0;  
  5.      if (DBG) Log.d(TAG, "List of available peers");  
  6.      for (WifiP2pDevice peer: mPeers.getDeviceList()) {  
  7.          if (DBG) Log.d(TAG, "-> " + peer);  
  8. //WifiP2pPeer是Preference的子类,它和UI相关  
  9.          mPeersGroup.addPreference(new WifiP2pPeer(getActivity(), peer));  
  10.          if (peer.status == WifiP2pDevice.CONNECTED) mConnectedDevices++;  
  11.      }  
  12.      if (DBG) Log.d(TAG, " mConnectedDevices " + mConnectedDevices);  
  13.  }  
在该函数中,WifiP2pDeviceList中保存的每一个WifiP2pDevice信息将作为一个Preference项添加到mPeersGroup中并显示在UI界面上。
接下来用户就可在界面中选择某个P2P设备并与之连接,这个步骤由onPreferenceTreeClick函数来完成。
[cpp] view plain copy
  1. public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {  
  2.     if (preference instanceof WifiP2pPeer) {  
  3.         mSelectedWifiPeer = (WifiP2pPeer) preference;//获取用户指定的那一个WifiP2pPeer项  
  4.         if (mSelectedWifiPeer.device.status == WifiP2pDevice.CONNECTED) {  
  5.             showDialog(DIALOG_DISCONNECT);//如果已经和该设备连接,则判断是否需要与之断开连接  
  6.         } else if (mSelectedWifiPeer.device.status == WifiP2pDevice.INVITED) {  
  7.             showDialog(DIALOG_CANCEL_CONNECT);  
  8.         } else {//向对端P2P设备发起连接  
  9.             WifiP2pConfig config = new WifiP2pConfig();  
  10.             config.deviceAddress = mSelectedWifiPeer.device.deviceAddress;  
  11.   
  12. //判断系统是否强制使用了某种WSC配置方法  
  13.             int forceWps = SystemProperties.getInt("wifidirect.wps", -1);  
  14.   
  15.             if (forceWps != -1) {  
  16.                 config.wps.setup = forceWps;  
  17.             } else {  
  18.     //获取对端P2P设备支持的WSC配置方法,优先考虑PBC  
  19.                 if (mSelectedWifiPeer.device.wpsPbcSupported()) {  
  20.                     config.wps.setup = WpsInfo.PBC;  
  21.                 } else if (mSelectedWifiPeer.device.wpsKeypadSupported()) {  
  22.                     config.wps.setup = WpsInfo.KEYPAD;  
  23.                 } else {  
  24.                     config.wps.setup = WpsInfo.DISPLAY;  
  25.                 }  
  26.             }  
  27.   
  28. //通过WifiP2pManager的connect函数向对端P2P设备发起连接。注意,目标设备信息保存在config对象中  
  29.             mWifiP2pManager.connect(mChannel, config,  
  30.                     new WifiP2pManager.ActionListener() {  
  31.                         public void onSuccess() {  
  32.                             if (DBG) Log.d(TAG, " connect success");  
  33.                         }  
  34.                         public void onFailure(int reason) {  
  35.                             Log.e(TAG, " connect fail " + reason);  
  36.                             Toast.makeText(getActivity(),  
  37.                                     R.string.wifi_p2p_failed_connect_message,  
  38.                                     Toast.LENGTH_SHORT).show();  
  39.                         }  
  40.                 });  
  41.         }  
  42.     } else if (preference instanceof WifiP2pPersistentGroup) {  
  43.         mSelectedGroup = (WifiP2pPersistentGroup) preference;  
  44.         showDialog(DIALOG_DELETE_GROUP);  
  45.     }  
  46.     return super.onPreferenceTreeClick(screen, preference);  
  47. }  

当系统完成和P2P设备的连接后,WifiP2pSettings将收到 WIFI_P2P_CONNECTION_CHANGED_ACTION 广播,对应的代码见onReceive

原创粉丝点击