在Android WIFI (一) 扫描WIFI中,我们介绍了如何扫描WIFI,本文介绍下如何连接WIFI。
权限
改变WIFI状态需要添加权限,如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
</manifest>
通过WifiConfiguration进行连接(已废弃)
通过WifiManager和WifiConfiguration连接WIFI。需要注意的是,此方式在Android Q(10)以后已经废弃,我的测试机(Android S)使用此方式无法连接WIFI。
未加密的WIFI
通过WifiManager和WifiConfiguration连接未加密的WIFI,代码如下:
class WIFIExampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
// 以扫描结果的第一项为例,实际应用按需调整
val wifiIfno = wifiManager.scanResults.first()
val ssid = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
it.wifiSsid.toString()
} else {
it.SSID
}
val wifiConfig = WifiConfiguration()
wifiConfig.SSID = "\"$ssid\""
wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
wifiManager.enableNetwork(addNetwork(wifiConfig), true)
}
}
加密类型为WEP的WIFI
通过WifiManager和WifiConfiguration连接加密类型为WEP的WIFI,代码如下:
class WIFIExampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
val wifiIfno = wifiManager.scanResults.first()
val ssid = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
it.wifiSsid.toString()
} else {
it.SSID
}
val wifiConfig = WifiConfiguration()
wifiConfig.SSID = "\"$ssid\""
wifiConfig.wepKeys[0] = "\"${WIFI的密码}\""
wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN)
wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED)
wifiManager.enableNetwork(addNetwork(wifiConfig), true)
}
}
此加密类型已经过时,基本不再使用。
加密类型为WPA的WIFI
通过WifiManager和WifiConfiguration连接加密类型为WPA的WIFI,代码如下:
class WIFIExampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
val wifiIfno = wifiManager.scanResults.first()
val ssid = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
it.wifiSsid.toString()
} else {
it.SSID
}
val wifiConfig = WifiConfiguration()
wifiConfig.SSID = "\"$ssid\""
wifiConfig.preSharedKey = "\"${WIFI的密码}\""
wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK)
wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA)
wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN)
wifiManager.enableNetwork(addNetwork(wifiConfig), true)
}
}
通过WifiNetworkSpecifier进行连接
可以通过ConnectivityManager和WifiNetworkSpecifier连接WIFI。
未加密的WIFI
通过ConnectivityManager和WifiNetworkSpecifier连接未加密的WIFI,代码如下:
class WIFIExampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val wifiIfno = wifiManager.scanResults.first()
val ssid = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
it.wifiSsid.toString()
} else {
it.SSID
}
val specifier = WifiNetworkSpecifier.Builder()
.setSsid(ssid)
.setBssid(MacAddress.fromString(wifiIfno.BSSID))
.build()
val request = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(specifier)
.build()
connectivityManager.requestNetwork(request, object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
connectivityManager.run {
if (boundNetworkForProcess != network) {
if (boundNetworkForProcess != network) {
bindProcessToNetwork(network)
}
}
}
}
})
}
}
加密类型为WPA的WIFI
通过ConnectivityManager和WifiNetworkSpecifier连接加密类型为WPA的WIFI,代码如下:
class WIFIExampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val wifiIfno = wifiManager.scanResults.first()
val ssid = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
it.wifiSsid.toString()
} else {
it.SSID
}
val specifierBuilder = WifiNetworkSpecifier.Builder()
.setSsid(ssid)
.setBssid(MacAddress.fromString(wifiIfno.BSSID))
if (wifiInfo.capabilities.contains("wpa3", true)) {
specifierBuilder.setWpa3Passphrase(password)
} else {
specifierBuilder.setWpa2Passphrase(password)
}
val request = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(specifierBuilder.build())
.build()
connectivityManager.requestNetwork(request, object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
connectivityManager.run {
if (boundNetworkForProcess != network) {
if (boundNetworkForProcess != network) {
bindProcessToNetwork(network)
}
}
}
}
})
}
}
测试结果(已更新)
效果如图:
| 外部浏览器 | 内置WebView |
|---|---|
可以看到,WIFI连接成功后,使用外部浏览器无法正常打开网页,App内置WebView则可以正常打开网页。个人认为,通过WifiNetworkSpecifier连接WIFI后,只有App使用的流量可以通过WIFI传输。
通过WifiNetworkSuggestion进行连接
可以通过WifiManager和WifiNetworkSuggestion连接WIFI。
需要注意,如果用户在系统的WIFI列表中断开某个已连接的建议WIFI,那么该WIFI会被拉入黑名单24小时。在黑名单期间,系统不会自动连接该WIFI,即使删除并重新添加建议也是如此。
未加密的WIFI
通过WifiManager和WifiNetworkSuggestion连接未加密的WIFI,代码如下:
class WIFIExampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
val wifiIfno = wifiManager.scanResults.first()
val ssid = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
it.wifiSsid.toString()
} else {
it.SSID
}
val suggestion = WifiNetworkSuggestion.Builder()
.setSsid(ssid)
.setBssid(MacAddress.fromString(wifiIfno.BSSID))
.build()
wifiManager?.addNetworkSuggestions(listOf(suggestion))
}
}
加密类型为WPA的WIFI
通过WifiManager和WifiNetworkSuggestion连接加密类型为WPA的WIFI,代码如下:
class WIFIExampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
val wifiIfno = wifiManager.scanResults.first()
val ssid = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
it.wifiSsid.toString()
} else {
it.SSID
}
val suggestionBuilder = WifiNetworkSuggestion.Builder()
.setSsid(ssid)
.setBssid(MacAddress.fromString(wifiIfno.BSSID))
if (wifiInfo.capabilities.contains("wpa3", true)) {
suggestionBuilder.setWpa3Passphrase(password)
} else {
suggestionBuilder.setWpa2Passphrase(password)
}
wifiManager.addNetworkSuggestions(listOf(suggestionBuilder.build()))
}
}
测试结果
效果如图:
可以看到,通过这种方式连接WIFI,可以正常的打开网页。
示例
在示例Demo中添加了相关的演示代码。