1. 程式人生 > >android 種的WiFi相關

android 種的WiFi相關

nor true 刷新 格式刷 too 否則 建立 .so ccm

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"/>的聲明

android 種的WiFi相關