android 种的WiFi相关

黄沙百战穿金甲,不破楼兰终不还。这篇文章主要讲述android 种的WiFi相关相关的知识,希望能为你提供帮助。
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();
}
【android 种的WiFi相关】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"/> 的声明


















































































































































































    推荐阅读