Android中WiFi相关的几个重要的类:
Wi-FiManager; Wi-FiConfiguration; Wi-FiInfo 我基本上是用到Wi-FiConfiguration和Wi-FiManager两个类; 与一个指定的WiFi相连: WiFi的SSID,WIFI的Passphrase,以及WiFi加密的类型(可粗略分为无密码,WEP,WPA三种) 源码: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Add a new network description to the set of configured networks. * The {@code networkId} field of the supplied configuration object * is ignored. * <p/> * The new network will be marked DISABLED by default. To enable it, * called {@link #enableNetwork}. * * @param config the set of variables that describe the configuration, * contained in a {@link WifiConfiguration} object. * If the {@link WifiConfiguration} has an Http Proxy set * the calling app must be System, or be provisioned as the Profile or Device Owner. * @return the ID of the newly created network description. This is used in * other operations to specified the network to be acted upon. * Returns {@code -1} on failure. */ public int addNetwork(WifiConfiguration config) { if (config == null) { return -1; } config.networkId = -1; return addOrUpdateNetwork(config); } /** * Allow a previously configured network to be associated with. If * <code>attemptConnect</code> is true, an attempt to connect to the selected * network is initiated. This may result in the asynchronous delivery * of state change events. * <p> * <b>Note:</b> If an application's target SDK version is * {@link android.os.Build.VERSION_CODES#LOLLIPOP} or newer, network * communication may not use Wi-Fi even if Wi-Fi is connected; traffic may * instead be sent through another network, such as cellular data, * Bluetooth tethering, or Ethernet. For example, traffic will never use a * Wi-Fi network that does not provide Internet access (e.g. a wireless * printer), if another network that does offer Internet access (e.g. * cellular data) is available. Applications that need to ensure that their * network traffic uses Wi-Fi should use APIs such as * {@link Network#bindSocket(java.net.Socket)}, * {@link Network#openConnection(java.net.URL)}, or * {@link ConnectivityManager#bindProcessToNetwork} to do so. * * Applications are not allowed to enable networks created by other * applications. * * @param netId the ID of the network as returned by {@link #addNetwork} or {@link * #getConfiguredNetworks}. * @param attemptConnect The way to select a particular network to connect to is specify * {@code true} for this parameter. * @return {@code true} if the operation succeeded */ public boolean enableNetwork(int netId, boolean attemptConnect) { final boolean pin = attemptConnect && mTargetSdkVersion < Build.VERSION_CODES.LOLLIPOP; if (pin) { NetworkRequest request = new NetworkRequest.Builder() .clearCapabilities() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .build(); NetworkPinner.pin(mContext, request); }boolean success;
try { success = mService.enableNetwork(netId, attemptConnect); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); }if (pin && !success) {
NetworkPinner.unpin(); }return success;
} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /** * Connect to a network with the given configuration. The network also * gets added to the list of configured networks for the foreground user. * * For a new network, this function is used instead of a * sequence of addNetwork(), enableNetwork(), saveConfiguration() and * reconnect() * * @param config the set of variables that describe the configuration, * contained in a {@link WifiConfiguration} object. * @param listener for callbacks on success or failure. Can be null. * @throws IllegalStateException if the WifiManager instance needs to be * initialized again * * @hide */ @SystemApi public void connect(WifiConfiguration config, ActionListener listener) { if (config == null) throw new IllegalArgumentException("config cannot be null"); // Use INVALID_NETWORK_ID for arg1 when passing a config object // arg1 is used to pass network id when the network already exists getChannel().sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID, putListener(listener), config); } 我们可以看到与新WiFi建立连接,可以通过addNetwork(Configuration)+enableNetwork(netID,true)去实现。addNework返回netID 同时也可以直接利用connect(Configuration)实现 不论用那种方法我们都需要一个Configuration实体。所以与新WiFi建立的关键在于得到一个正确的Configuration实体。 代码: private WifiConfiguration createWifiInfo(String SSID, String Password, WifiCipherType Type) { WifiConfiguration config = new WifiConfiguration(); config.allowedAuthAlgorithms.clear(); config.allowedGroupCiphers.clear(); config.allowedKeyManagement.clear(); config.allowedPairwiseCiphers.clear(); config.allowedProtocols.clear(); config.SSID = "\"" + SSID + "\""; // nopass if (Type == WifiCipherType.WIFICIPHER_NOPASS) { // config.wepKeys[0] = ""; config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); // config.wepTxKeyIndex = 0; } // wep if (Type == WifiCipherType.WIFICIPHER_WEP) { if (!TextUtils.isEmpty(Password)) { if (isHexWepKey(Password)) { config.wepKeys[0] = Password; } else { config.wepKeys[0] = "\"" + Password + "\""; } } config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN); config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED); config.allowedKeyManagement.set(KeyMgmt.NONE); config.wepTxKeyIndex = 0; } // wpa if (Type == WifiCipherType.WIFICIPHER_WPA) { config.preSharedKey = "\"" + Password + "\""; config.hiddenSSID = true; config.allowedAuthAlgorithms .set(WifiConfiguration.AuthAlgorithm.OPEN); config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); config.allowedPairwiseCiphers .set(WifiConfiguration.PairwiseCipher.TKIP); // 此处需要修改否则不能自动重联 // config.allowedProtocols.set(WifiConfiguration.Protocol.WPA); config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); config.allowedPairwiseCiphers .set(WifiConfiguration.PairwiseCipher.CCMP); config.status = WifiConfiguration.Status.ENABLED; } return config; } 124-128行中,各种.clear()方法的调用,可以看做是一种格式刷新。 因为Wifi连接存在多种加密方式,首先我们对各种连接格式进行刷新。 然后,粗略分为三种模式:无密码,WEP,WPA(后两种是指两种加密格式,其实存在更细粒度的划分) 然后对于不同的模式,我们将SSID和Passphrase进行对应的配置(现在并没有看懂这些配置的过程~~) 通过以上代码,我们可以获取一个Configuration对象,这样再调用连接方法就可以连接到指定的WiFi了。 注意: 1、在Android上开发时需要给与一些权限: <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 2、<uses-feature android:name="android.hardware.wifi"/>的声明